xref: /openbmc/qemu/block/ssh.c (revision 8f968b6a24aec7de8b1a1b4d2de922adad689297)
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 <libssh/libssh.h>
28  #include <libssh/sftp.h>
29  
30  #include "block/block_int.h"
31  #include "block/qdict.h"
32  #include "qapi/error.h"
33  #include "qemu/error-report.h"
34  #include "qemu/module.h"
35  #include "qemu/option.h"
36  #include "qemu/ctype.h"
37  #include "qemu/cutils.h"
38  #include "qemu/sockets.h"
39  #include "qemu/uri.h"
40  #include "qapi/qapi-visit-sockets.h"
41  #include "qapi/qapi-visit-block-core.h"
42  #include "qapi/qmp/qdict.h"
43  #include "qapi/qmp/qstring.h"
44  #include "qapi/qobject-input-visitor.h"
45  #include "qapi/qobject-output-visitor.h"
46  #include "trace.h"
47  
48  /*
49   * TRACE_LIBSSH=<level> enables tracing in libssh itself.
50   * The meaning of <level> is described here:
51   * http://api.libssh.org/master/group__libssh__log.html
52   */
53  #define TRACE_LIBSSH  0 /* see: SSH_LOG_* */
54  
55  typedef struct BDRVSSHState {
56      /* Coroutine. */
57      CoMutex lock;
58  
59      /* SSH connection. */
60      int sock;                         /* socket */
61      ssh_session session;              /* ssh session */
62      sftp_session sftp;                /* sftp session */
63      sftp_file sftp_handle;            /* sftp remote file handle */
64  
65      /*
66       * File attributes at open.  We try to keep the .size field
67       * updated if it changes (eg by writing at the end of the file).
68       */
69      sftp_attributes attrs;
70  
71      InetSocketAddress *inet;
72  
73      /* Used to warn if 'flush' is not supported. */
74      bool unsafe_flush_warning;
75  
76      /*
77       * Store the user name for ssh_refresh_filename() because the
78       * default depends on the system you are on -- therefore, when we
79       * generate a filename, it should always contain the user name we
80       * are actually using.
81       */
82      char *user;
83  } BDRVSSHState;
84  
85  static void ssh_state_init(BDRVSSHState *s)
86  {
87      memset(s, 0, sizeof *s);
88      s->sock = -1;
89      qemu_co_mutex_init(&s->lock);
90  }
91  
92  static void ssh_state_free(BDRVSSHState *s)
93  {
94      g_free(s->user);
95  
96      if (s->attrs) {
97          sftp_attributes_free(s->attrs);
98      }
99      if (s->sftp_handle) {
100          sftp_close(s->sftp_handle);
101      }
102      if (s->sftp) {
103          sftp_free(s->sftp);
104      }
105      if (s->session) {
106          ssh_disconnect(s->session);
107          ssh_free(s->session); /* This frees s->sock */
108      }
109  }
110  
111  static void GCC_FMT_ATTR(3, 4)
112  session_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...)
113  {
114      va_list args;
115      char *msg;
116  
117      va_start(args, fs);
118      msg = g_strdup_vprintf(fs, args);
119      va_end(args);
120  
121      if (s->session) {
122          const char *ssh_err;
123          int ssh_err_code;
124  
125          /* This is not an errno.  See <libssh/libssh.h>. */
126          ssh_err = ssh_get_error(s->session);
127          ssh_err_code = ssh_get_error_code(s->session);
128          error_setg(errp, "%s: %s (libssh error code: %d)",
129                     msg, ssh_err, ssh_err_code);
130      } else {
131          error_setg(errp, "%s", msg);
132      }
133      g_free(msg);
134  }
135  
136  static void GCC_FMT_ATTR(3, 4)
137  sftp_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...)
138  {
139      va_list args;
140      char *msg;
141  
142      va_start(args, fs);
143      msg = g_strdup_vprintf(fs, args);
144      va_end(args);
145  
146      if (s->sftp) {
147          const char *ssh_err;
148          int ssh_err_code;
149          int sftp_err_code;
150  
151          /* This is not an errno.  See <libssh/libssh.h>. */
152          ssh_err = ssh_get_error(s->session);
153          ssh_err_code = ssh_get_error_code(s->session);
154          /* See <libssh/sftp.h>. */
155          sftp_err_code = sftp_get_error(s->sftp);
156  
157          error_setg(errp,
158                     "%s: %s (libssh error code: %d, sftp error code: %d)",
159                     msg, ssh_err, ssh_err_code, sftp_err_code);
160      } else {
161          error_setg(errp, "%s", msg);
162      }
163      g_free(msg);
164  }
165  
166  static void sftp_error_trace(BDRVSSHState *s, const char *op)
167  {
168      const char *ssh_err;
169      int ssh_err_code;
170      int sftp_err_code;
171  
172      /* This is not an errno.  See <libssh/libssh.h>. */
173      ssh_err = ssh_get_error(s->session);
174      ssh_err_code = ssh_get_error_code(s->session);
175      /* See <libssh/sftp.h>. */
176      sftp_err_code = sftp_get_error(s->sftp);
177  
178      trace_sftp_error(op, ssh_err, ssh_err_code, sftp_err_code);
179  }
180  
181  static int parse_uri(const char *filename, QDict *options, Error **errp)
182  {
183      URI *uri = NULL;
184      QueryParams *qp;
185      char *port_str;
186      int i;
187  
188      uri = uri_parse(filename);
189      if (!uri) {
190          return -EINVAL;
191      }
192  
193      if (g_strcmp0(uri->scheme, "ssh") != 0) {
194          error_setg(errp, "URI scheme must be 'ssh'");
195          goto err;
196      }
197  
198      if (!uri->server || strcmp(uri->server, "") == 0) {
199          error_setg(errp, "missing hostname in URI");
200          goto err;
201      }
202  
203      if (!uri->path || strcmp(uri->path, "") == 0) {
204          error_setg(errp, "missing remote path in URI");
205          goto err;
206      }
207  
208      qp = query_params_parse(uri->query);
209      if (!qp) {
210          error_setg(errp, "could not parse query parameters");
211          goto err;
212      }
213  
214      if(uri->user && strcmp(uri->user, "") != 0) {
215          qdict_put_str(options, "user", uri->user);
216      }
217  
218      qdict_put_str(options, "server.host", uri->server);
219  
220      port_str = g_strdup_printf("%d", uri->port ?: 22);
221      qdict_put_str(options, "server.port", port_str);
222      g_free(port_str);
223  
224      qdict_put_str(options, "path", uri->path);
225  
226      /* Pick out any query parameters that we understand, and ignore
227       * the rest.
228       */
229      for (i = 0; i < qp->n; ++i) {
230          if (strcmp(qp->p[i].name, "host_key_check") == 0) {
231              qdict_put_str(options, "host_key_check", qp->p[i].value);
232          }
233      }
234  
235      query_params_free(qp);
236      uri_free(uri);
237      return 0;
238  
239   err:
240      uri_free(uri);
241      return -EINVAL;
242  }
243  
244  static bool ssh_has_filename_options_conflict(QDict *options, Error **errp)
245  {
246      const QDictEntry *qe;
247  
248      for (qe = qdict_first(options); qe; qe = qdict_next(options, qe)) {
249          if (!strcmp(qe->key, "host") ||
250              !strcmp(qe->key, "port") ||
251              !strcmp(qe->key, "path") ||
252              !strcmp(qe->key, "user") ||
253              !strcmp(qe->key, "host_key_check") ||
254              strstart(qe->key, "server.", NULL))
255          {
256              error_setg(errp, "Option '%s' cannot be used with a file name",
257                         qe->key);
258              return true;
259          }
260      }
261  
262      return false;
263  }
264  
265  static void ssh_parse_filename(const char *filename, QDict *options,
266                                 Error **errp)
267  {
268      if (ssh_has_filename_options_conflict(options, errp)) {
269          return;
270      }
271  
272      parse_uri(filename, options, errp);
273  }
274  
275  static int check_host_key_knownhosts(BDRVSSHState *s, Error **errp)
276  {
277      int ret;
278      enum ssh_known_hosts_e state;
279      int r;
280      ssh_key pubkey;
281      enum ssh_keytypes_e pubkey_type;
282      unsigned char *server_hash = NULL;
283      size_t server_hash_len;
284      char *fingerprint = NULL;
285  
286      state = ssh_session_is_known_server(s->session);
287      trace_ssh_server_status(state);
288  
289      switch (state) {
290      case SSH_KNOWN_HOSTS_OK:
291          /* OK */
292          trace_ssh_check_host_key_knownhosts();
293          break;
294      case SSH_KNOWN_HOSTS_CHANGED:
295          ret = -EINVAL;
296          r = ssh_get_server_publickey(s->session, &pubkey);
297          if (r == 0) {
298              r = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA256,
299                                         &server_hash, &server_hash_len);
300              pubkey_type = ssh_key_type(pubkey);
301              ssh_key_free(pubkey);
302          }
303          if (r == 0) {
304              fingerprint = ssh_get_fingerprint_hash(SSH_PUBLICKEY_HASH_SHA256,
305                                                     server_hash,
306                                                     server_hash_len);
307              ssh_clean_pubkey_hash(&server_hash);
308          }
309          if (fingerprint) {
310              error_setg(errp,
311                         "host key (%s key with fingerprint %s) does not match "
312                         "the one in known_hosts; this may be a possible attack",
313                         ssh_key_type_to_char(pubkey_type), fingerprint);
314              ssh_string_free_char(fingerprint);
315          } else  {
316              error_setg(errp,
317                         "host key does not match the one in known_hosts; this "
318                         "may be a possible attack");
319          }
320          goto out;
321      case SSH_KNOWN_HOSTS_OTHER:
322          ret = -EINVAL;
323          error_setg(errp,
324                     "host key for this server not found, another type exists");
325          goto out;
326      case SSH_KNOWN_HOSTS_UNKNOWN:
327          ret = -EINVAL;
328          error_setg(errp, "no host key was found in known_hosts");
329          goto out;
330      case SSH_KNOWN_HOSTS_NOT_FOUND:
331          ret = -ENOENT;
332          error_setg(errp, "known_hosts file not found");
333          goto out;
334      case SSH_KNOWN_HOSTS_ERROR:
335          ret = -EINVAL;
336          error_setg(errp, "error while checking the host");
337          goto out;
338      default:
339          ret = -EINVAL;
340          error_setg(errp, "error while checking for known server (%d)", state);
341          goto out;
342      }
343  
344      /* known_hosts checking successful. */
345      ret = 0;
346  
347   out:
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                      enum ssh_publickey_hash_type type, Error **errp)
392  {
393      int r;
394      ssh_key pubkey;
395      unsigned char *server_hash;
396      size_t server_hash_len;
397  
398      r = ssh_get_server_publickey(s->session, &pubkey);
399      if (r != SSH_OK) {
400          session_error_setg(errp, s, "failed to read remote host key");
401          return -EINVAL;
402      }
403  
404      r = ssh_get_publickey_hash(pubkey, type, &server_hash, &server_hash_len);
405      ssh_key_free(pubkey);
406      if (r != 0) {
407          session_error_setg(errp, s,
408                             "failed reading the hash of the server SSH key");
409          return -EINVAL;
410      }
411  
412      r = compare_fingerprint(server_hash, server_hash_len, hash);
413      ssh_clean_pubkey_hash(&server_hash);
414      if (r != 0) {
415          error_setg(errp, "remote host key does not match host_key_check '%s'",
416                     hash);
417          return -EPERM;
418      }
419  
420      return 0;
421  }
422  
423  static int check_host_key(BDRVSSHState *s, SshHostKeyCheck *hkc, Error **errp)
424  {
425      SshHostKeyCheckMode mode;
426  
427      if (hkc) {
428          mode = hkc->mode;
429      } else {
430          mode = SSH_HOST_KEY_CHECK_MODE_KNOWN_HOSTS;
431      }
432  
433      switch (mode) {
434      case SSH_HOST_KEY_CHECK_MODE_NONE:
435          return 0;
436      case SSH_HOST_KEY_CHECK_MODE_HASH:
437          if (hkc->u.hash.type == SSH_HOST_KEY_CHECK_HASH_TYPE_MD5) {
438              return check_host_key_hash(s, hkc->u.hash.hash,
439                                         SSH_PUBLICKEY_HASH_MD5, errp);
440          } else if (hkc->u.hash.type == SSH_HOST_KEY_CHECK_HASH_TYPE_SHA1) {
441              return check_host_key_hash(s, hkc->u.hash.hash,
442                                         SSH_PUBLICKEY_HASH_SHA1, errp);
443          } else if (hkc->u.hash.type == SSH_HOST_KEY_CHECK_HASH_TYPE_SHA256) {
444              return check_host_key_hash(s, hkc->u.hash.hash,
445                                         SSH_PUBLICKEY_HASH_SHA256, errp);
446          }
447          g_assert_not_reached();
448          break;
449      case SSH_HOST_KEY_CHECK_MODE_KNOWN_HOSTS:
450          return check_host_key_knownhosts(s, errp);
451      default:
452          g_assert_not_reached();
453      }
454  
455      return -EINVAL;
456  }
457  
458  static int authenticate(BDRVSSHState *s, Error **errp)
459  {
460      int r, ret;
461      int method;
462  
463      /* Try to authenticate with the "none" method. */
464      r = ssh_userauth_none(s->session, NULL);
465      if (r == SSH_AUTH_ERROR) {
466          ret = -EPERM;
467          session_error_setg(errp, s, "failed to authenticate using none "
468                                      "authentication");
469          goto out;
470      } else if (r == SSH_AUTH_SUCCESS) {
471          /* Authenticated! */
472          ret = 0;
473          goto out;
474      }
475  
476      method = ssh_userauth_list(s->session, NULL);
477      trace_ssh_auth_methods(method);
478  
479      /*
480       * Try to authenticate with publickey, using the ssh-agent
481       * if available.
482       */
483      if (method & SSH_AUTH_METHOD_PUBLICKEY) {
484          r = ssh_userauth_publickey_auto(s->session, NULL, NULL);
485          if (r == SSH_AUTH_ERROR) {
486              ret = -EINVAL;
487              session_error_setg(errp, s, "failed to authenticate using "
488                                          "publickey authentication");
489              goto out;
490          } else if (r == SSH_AUTH_SUCCESS) {
491              /* Authenticated! */
492              ret = 0;
493              goto out;
494          }
495      }
496  
497      ret = -EPERM;
498      error_setg(errp, "failed to authenticate using publickey authentication "
499                 "and the identities held by your ssh-agent");
500  
501   out:
502      return ret;
503  }
504  
505  static QemuOptsList ssh_runtime_opts = {
506      .name = "ssh",
507      .head = QTAILQ_HEAD_INITIALIZER(ssh_runtime_opts.head),
508      .desc = {
509          {
510              .name = "host",
511              .type = QEMU_OPT_STRING,
512              .help = "Host to connect to",
513          },
514          {
515              .name = "port",
516              .type = QEMU_OPT_NUMBER,
517              .help = "Port to connect to",
518          },
519          {
520              .name = "host_key_check",
521              .type = QEMU_OPT_STRING,
522              .help = "Defines how and what to check the host key against",
523          },
524          { /* end of list */ }
525      },
526  };
527  
528  static bool ssh_process_legacy_options(QDict *output_opts,
529                                         QemuOpts *legacy_opts,
530                                         Error **errp)
531  {
532      const char *host = qemu_opt_get(legacy_opts, "host");
533      const char *port = qemu_opt_get(legacy_opts, "port");
534      const char *host_key_check = qemu_opt_get(legacy_opts, "host_key_check");
535  
536      if (!host && port) {
537          error_setg(errp, "port may not be used without host");
538          return false;
539      }
540  
541      if (host) {
542          qdict_put_str(output_opts, "server.host", host);
543          qdict_put_str(output_opts, "server.port", port ?: stringify(22));
544      }
545  
546      if (host_key_check) {
547          if (strcmp(host_key_check, "no") == 0) {
548              qdict_put_str(output_opts, "host-key-check.mode", "none");
549          } else if (strncmp(host_key_check, "md5:", 4) == 0) {
550              qdict_put_str(output_opts, "host-key-check.mode", "hash");
551              qdict_put_str(output_opts, "host-key-check.type", "md5");
552              qdict_put_str(output_opts, "host-key-check.hash",
553                            &host_key_check[4]);
554          } else if (strncmp(host_key_check, "sha1:", 5) == 0) {
555              qdict_put_str(output_opts, "host-key-check.mode", "hash");
556              qdict_put_str(output_opts, "host-key-check.type", "sha1");
557              qdict_put_str(output_opts, "host-key-check.hash",
558                            &host_key_check[5]);
559          } else if (strcmp(host_key_check, "yes") == 0) {
560              qdict_put_str(output_opts, "host-key-check.mode", "known_hosts");
561          } else {
562              error_setg(errp, "unknown host_key_check setting (%s)",
563                         host_key_check);
564              return false;
565          }
566      }
567  
568      return true;
569  }
570  
571  static BlockdevOptionsSsh *ssh_parse_options(QDict *options, Error **errp)
572  {
573      BlockdevOptionsSsh *result = NULL;
574      QemuOpts *opts = NULL;
575      const QDictEntry *e;
576      Visitor *v;
577  
578      /* Translate legacy options */
579      opts = qemu_opts_create(&ssh_runtime_opts, NULL, 0, &error_abort);
580      if (!qemu_opts_absorb_qdict(opts, options, errp)) {
581          goto fail;
582      }
583  
584      if (!ssh_process_legacy_options(options, opts, errp)) {
585          goto fail;
586      }
587  
588      /* Create the QAPI object */
589      v = qobject_input_visitor_new_flat_confused(options, errp);
590      if (!v) {
591          goto fail;
592      }
593  
594      visit_type_BlockdevOptionsSsh(v, NULL, &result, errp);
595      visit_free(v);
596      if (!result) {
597          goto fail;
598      }
599  
600      /* Remove the processed options from the QDict (the visitor processes
601       * _all_ options in the QDict) */
602      while ((e = qdict_first(options))) {
603          qdict_del(options, e->key);
604      }
605  
606  fail:
607      qemu_opts_del(opts);
608      return result;
609  }
610  
611  static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts,
612                            int ssh_flags, int creat_mode, Error **errp)
613  {
614      int r, ret;
615      unsigned int port = 0;
616      int new_sock = -1;
617  
618      if (opts->has_user) {
619          s->user = g_strdup(opts->user);
620      } else {
621          s->user = g_strdup(g_get_user_name());
622          if (!s->user) {
623              error_setg_errno(errp, errno, "Can't get user name");
624              ret = -errno;
625              goto err;
626          }
627      }
628  
629      /* Pop the config into our state object, Exit if invalid */
630      s->inet = opts->server;
631      opts->server = NULL;
632  
633      if (qemu_strtoui(s->inet->port, NULL, 10, &port) < 0) {
634          error_setg(errp, "Use only numeric port value");
635          ret = -EINVAL;
636          goto err;
637      }
638  
639      /* Open the socket and connect. */
640      new_sock = inet_connect_saddr(s->inet, errp);
641      if (new_sock < 0) {
642          ret = -EIO;
643          goto err;
644      }
645  
646      /*
647       * Try to disable the Nagle algorithm on TCP sockets to reduce latency,
648       * but do not fail if it cannot be disabled.
649       */
650      r = socket_set_nodelay(new_sock);
651      if (r < 0) {
652          warn_report("can't set TCP_NODELAY for the ssh server %s: %s",
653                      s->inet->host, strerror(errno));
654      }
655  
656      /* Create SSH session. */
657      s->session = ssh_new();
658      if (!s->session) {
659          ret = -EINVAL;
660          session_error_setg(errp, s, "failed to initialize libssh session");
661          goto err;
662      }
663  
664      /*
665       * Make sure we are in blocking mode during the connection and
666       * authentication phases.
667       */
668      ssh_set_blocking(s->session, 1);
669  
670      r = ssh_options_set(s->session, SSH_OPTIONS_USER, s->user);
671      if (r < 0) {
672          ret = -EINVAL;
673          session_error_setg(errp, s,
674                             "failed to set the user in the libssh session");
675          goto err;
676      }
677  
678      r = ssh_options_set(s->session, SSH_OPTIONS_HOST, s->inet->host);
679      if (r < 0) {
680          ret = -EINVAL;
681          session_error_setg(errp, s,
682                             "failed to set the host in the libssh session");
683          goto err;
684      }
685  
686      if (port > 0) {
687          r = ssh_options_set(s->session, SSH_OPTIONS_PORT, &port);
688          if (r < 0) {
689              ret = -EINVAL;
690              session_error_setg(errp, s,
691                                 "failed to set the port in the libssh session");
692              goto err;
693          }
694      }
695  
696      r = ssh_options_set(s->session, SSH_OPTIONS_COMPRESSION, "none");
697      if (r < 0) {
698          ret = -EINVAL;
699          session_error_setg(errp, s,
700                             "failed to disable the compression in the libssh "
701                             "session");
702          goto err;
703      }
704  
705      /* Read ~/.ssh/config. */
706      r = ssh_options_parse_config(s->session, NULL);
707      if (r < 0) {
708          ret = -EINVAL;
709          session_error_setg(errp, s, "failed to parse ~/.ssh/config");
710          goto err;
711      }
712  
713      r = ssh_options_set(s->session, SSH_OPTIONS_FD, &new_sock);
714      if (r < 0) {
715          ret = -EINVAL;
716          session_error_setg(errp, s,
717                             "failed to set the socket in the libssh session");
718          goto err;
719      }
720      /* libssh took ownership of the socket. */
721      s->sock = new_sock;
722      new_sock = -1;
723  
724      /* Connect. */
725      r = ssh_connect(s->session);
726      if (r != SSH_OK) {
727          ret = -EINVAL;
728          session_error_setg(errp, s, "failed to establish SSH session");
729          goto err;
730      }
731  
732      /* Check the remote host's key against known_hosts. */
733      ret = check_host_key(s, opts->host_key_check, errp);
734      if (ret < 0) {
735          goto err;
736      }
737  
738      /* Authenticate. */
739      ret = authenticate(s, errp);
740      if (ret < 0) {
741          goto err;
742      }
743  
744      /* Start SFTP. */
745      s->sftp = sftp_new(s->session);
746      if (!s->sftp) {
747          session_error_setg(errp, s, "failed to create sftp handle");
748          ret = -EINVAL;
749          goto err;
750      }
751  
752      r = sftp_init(s->sftp);
753      if (r < 0) {
754          sftp_error_setg(errp, s, "failed to initialize sftp handle");
755          ret = -EINVAL;
756          goto err;
757      }
758  
759      /* Open the remote file. */
760      trace_ssh_connect_to_ssh(opts->path, ssh_flags, creat_mode);
761      s->sftp_handle = sftp_open(s->sftp, opts->path, ssh_flags, creat_mode);
762      if (!s->sftp_handle) {
763          sftp_error_setg(errp, s, "failed to open remote file '%s'",
764                          opts->path);
765          ret = -EINVAL;
766          goto err;
767      }
768  
769      /* Make sure the SFTP file is handled in blocking mode. */
770      sftp_file_set_blocking(s->sftp_handle);
771  
772      s->attrs = sftp_fstat(s->sftp_handle);
773      if (!s->attrs) {
774          sftp_error_setg(errp, s, "failed to read file attributes");
775          return -EINVAL;
776      }
777  
778      return 0;
779  
780   err:
781      if (s->attrs) {
782          sftp_attributes_free(s->attrs);
783      }
784      s->attrs = NULL;
785      if (s->sftp_handle) {
786          sftp_close(s->sftp_handle);
787      }
788      s->sftp_handle = NULL;
789      if (s->sftp) {
790          sftp_free(s->sftp);
791      }
792      s->sftp = NULL;
793      if (s->session) {
794          ssh_disconnect(s->session);
795          ssh_free(s->session);
796      }
797      s->session = NULL;
798      s->sock = -1;
799      if (new_sock >= 0) {
800          close(new_sock);
801      }
802  
803      return ret;
804  }
805  
806  static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
807                           Error **errp)
808  {
809      BDRVSSHState *s = bs->opaque;
810      BlockdevOptionsSsh *opts;
811      int ret;
812      int ssh_flags;
813  
814      ssh_state_init(s);
815  
816      ssh_flags = 0;
817      if (bdrv_flags & BDRV_O_RDWR) {
818          ssh_flags |= O_RDWR;
819      } else {
820          ssh_flags |= O_RDONLY;
821      }
822  
823      opts = ssh_parse_options(options, errp);
824      if (opts == NULL) {
825          return -EINVAL;
826      }
827  
828      /* Start up SSH. */
829      ret = connect_to_ssh(s, opts, ssh_flags, 0, errp);
830      if (ret < 0) {
831          goto err;
832      }
833  
834      /* Go non-blocking. */
835      ssh_set_blocking(s->session, 0);
836  
837      if (s->attrs->type == SSH_FILEXFER_TYPE_REGULAR) {
838          bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
839      }
840  
841      qapi_free_BlockdevOptionsSsh(opts);
842  
843      return 0;
844  
845   err:
846      qapi_free_BlockdevOptionsSsh(opts);
847  
848      return ret;
849  }
850  
851  /* Note: This is a blocking operation */
852  static int ssh_grow_file(BDRVSSHState *s, int64_t offset, Error **errp)
853  {
854      ssize_t ret;
855      char c[1] = { '\0' };
856      int was_blocking = ssh_is_blocking(s->session);
857  
858      /* offset must be strictly greater than the current size so we do
859       * not overwrite anything */
860      assert(offset > 0 && offset > s->attrs->size);
861  
862      ssh_set_blocking(s->session, 1);
863  
864      sftp_seek64(s->sftp_handle, offset - 1);
865      ret = sftp_write(s->sftp_handle, c, 1);
866  
867      ssh_set_blocking(s->session, was_blocking);
868  
869      if (ret < 0) {
870          sftp_error_setg(errp, s, "Failed to grow file");
871          return -EIO;
872      }
873  
874      s->attrs->size = offset;
875      return 0;
876  }
877  
878  static QemuOptsList ssh_create_opts = {
879      .name = "ssh-create-opts",
880      .head = QTAILQ_HEAD_INITIALIZER(ssh_create_opts.head),
881      .desc = {
882          {
883              .name = BLOCK_OPT_SIZE,
884              .type = QEMU_OPT_SIZE,
885              .help = "Virtual disk size"
886          },
887          { /* end of list */ }
888      }
889  };
890  
891  static int ssh_co_create(BlockdevCreateOptions *options, Error **errp)
892  {
893      BlockdevCreateOptionsSsh *opts = &options->u.ssh;
894      BDRVSSHState s;
895      int ret;
896  
897      assert(options->driver == BLOCKDEV_DRIVER_SSH);
898  
899      ssh_state_init(&s);
900  
901      ret = connect_to_ssh(&s, opts->location,
902                           O_RDWR | O_CREAT | O_TRUNC,
903                           0644, errp);
904      if (ret < 0) {
905          goto fail;
906      }
907  
908      if (opts->size > 0) {
909          ret = ssh_grow_file(&s, opts->size, errp);
910          if (ret < 0) {
911              goto fail;
912          }
913      }
914  
915      ret = 0;
916  fail:
917      ssh_state_free(&s);
918      return ret;
919  }
920  
921  static int coroutine_fn ssh_co_create_opts(BlockDriver *drv,
922                                             const char *filename,
923                                             QemuOpts *opts,
924                                             Error **errp)
925  {
926      BlockdevCreateOptions *create_options;
927      BlockdevCreateOptionsSsh *ssh_opts;
928      int ret;
929      QDict *uri_options = NULL;
930  
931      create_options = g_new0(BlockdevCreateOptions, 1);
932      create_options->driver = BLOCKDEV_DRIVER_SSH;
933      ssh_opts = &create_options->u.ssh;
934  
935      /* Get desired file size. */
936      ssh_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
937                                BDRV_SECTOR_SIZE);
938      trace_ssh_co_create_opts(ssh_opts->size);
939  
940      uri_options = qdict_new();
941      ret = parse_uri(filename, uri_options, errp);
942      if (ret < 0) {
943          goto out;
944      }
945  
946      ssh_opts->location = ssh_parse_options(uri_options, errp);
947      if (ssh_opts->location == NULL) {
948          ret = -EINVAL;
949          goto out;
950      }
951  
952      ret = ssh_co_create(create_options, errp);
953  
954   out:
955      qobject_unref(uri_options);
956      qapi_free_BlockdevCreateOptions(create_options);
957      return ret;
958  }
959  
960  static void ssh_close(BlockDriverState *bs)
961  {
962      BDRVSSHState *s = bs->opaque;
963  
964      ssh_state_free(s);
965  }
966  
967  static int ssh_has_zero_init(BlockDriverState *bs)
968  {
969      BDRVSSHState *s = bs->opaque;
970      /* Assume false, unless we can positively prove it's true. */
971      int has_zero_init = 0;
972  
973      if (s->attrs->type == SSH_FILEXFER_TYPE_REGULAR) {
974          has_zero_init = 1;
975      }
976  
977      return has_zero_init;
978  }
979  
980  typedef struct BDRVSSHRestart {
981      BlockDriverState *bs;
982      Coroutine *co;
983  } BDRVSSHRestart;
984  
985  static void restart_coroutine(void *opaque)
986  {
987      BDRVSSHRestart *restart = opaque;
988      BlockDriverState *bs = restart->bs;
989      BDRVSSHState *s = bs->opaque;
990      AioContext *ctx = bdrv_get_aio_context(bs);
991  
992      trace_ssh_restart_coroutine(restart->co);
993      aio_set_fd_handler(ctx, s->sock, false, NULL, NULL, NULL, NULL);
994  
995      aio_co_wake(restart->co);
996  }
997  
998  /* A non-blocking call returned EAGAIN, so yield, ensuring the
999   * handlers are set up so that we'll be rescheduled when there is an
1000   * interesting event on the socket.
1001   */
1002  static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs)
1003  {
1004      int r;
1005      IOHandler *rd_handler = NULL, *wr_handler = NULL;
1006      BDRVSSHRestart restart = {
1007          .bs = bs,
1008          .co = qemu_coroutine_self()
1009      };
1010  
1011      r = ssh_get_poll_flags(s->session);
1012  
1013      if (r & SSH_READ_PENDING) {
1014          rd_handler = restart_coroutine;
1015      }
1016      if (r & SSH_WRITE_PENDING) {
1017          wr_handler = restart_coroutine;
1018      }
1019  
1020      trace_ssh_co_yield(s->sock, rd_handler, wr_handler);
1021  
1022      aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
1023                         false, rd_handler, wr_handler, NULL, &restart);
1024      qemu_coroutine_yield();
1025      trace_ssh_co_yield_back(s->sock);
1026  }
1027  
1028  static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs,
1029                                   int64_t offset, size_t size,
1030                                   QEMUIOVector *qiov)
1031  {
1032      ssize_t r;
1033      size_t got;
1034      char *buf, *end_of_vec;
1035      struct iovec *i;
1036  
1037      trace_ssh_read(offset, size);
1038  
1039      trace_ssh_seek(offset);
1040      sftp_seek64(s->sftp_handle, offset);
1041  
1042      /* This keeps track of the current iovec element ('i'), where we
1043       * will write to next ('buf'), and the end of the current iovec
1044       * ('end_of_vec').
1045       */
1046      i = &qiov->iov[0];
1047      buf = i->iov_base;
1048      end_of_vec = i->iov_base + i->iov_len;
1049  
1050      for (got = 0; got < size; ) {
1051          size_t request_read_size;
1052      again:
1053          /*
1054           * The size of SFTP packets is limited to 32K bytes, so limit
1055           * the amount of data requested to 16K, as libssh currently
1056           * does not handle multiple requests on its own.
1057           */
1058          request_read_size = MIN(end_of_vec - buf, 16384);
1059          trace_ssh_read_buf(buf, end_of_vec - buf, request_read_size);
1060          r = sftp_read(s->sftp_handle, buf, request_read_size);
1061          trace_ssh_read_return(r, sftp_get_error(s->sftp));
1062  
1063          if (r == SSH_AGAIN) {
1064              co_yield(s, bs);
1065              goto again;
1066          }
1067          if (r == SSH_EOF || (r == 0 && sftp_get_error(s->sftp) == SSH_FX_EOF)) {
1068              /* EOF: Short read so pad the buffer with zeroes and return it. */
1069              qemu_iovec_memset(qiov, got, 0, size - got);
1070              return 0;
1071          }
1072          if (r <= 0) {
1073              sftp_error_trace(s, "read");
1074              return -EIO;
1075          }
1076  
1077          got += r;
1078          buf += r;
1079          if (buf >= end_of_vec && got < size) {
1080              i++;
1081              buf = i->iov_base;
1082              end_of_vec = i->iov_base + i->iov_len;
1083          }
1084      }
1085  
1086      return 0;
1087  }
1088  
1089  static coroutine_fn int ssh_co_readv(BlockDriverState *bs,
1090                                       int64_t sector_num,
1091                                       int nb_sectors, QEMUIOVector *qiov)
1092  {
1093      BDRVSSHState *s = bs->opaque;
1094      int ret;
1095  
1096      qemu_co_mutex_lock(&s->lock);
1097      ret = ssh_read(s, bs, sector_num * BDRV_SECTOR_SIZE,
1098                     nb_sectors * BDRV_SECTOR_SIZE, qiov);
1099      qemu_co_mutex_unlock(&s->lock);
1100  
1101      return ret;
1102  }
1103  
1104  static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
1105                       int64_t offset, size_t size,
1106                       QEMUIOVector *qiov)
1107  {
1108      ssize_t r;
1109      size_t written;
1110      char *buf, *end_of_vec;
1111      struct iovec *i;
1112  
1113      trace_ssh_write(offset, size);
1114  
1115      trace_ssh_seek(offset);
1116      sftp_seek64(s->sftp_handle, offset);
1117  
1118      /* This keeps track of the current iovec element ('i'), where we
1119       * will read from next ('buf'), and the end of the current iovec
1120       * ('end_of_vec').
1121       */
1122      i = &qiov->iov[0];
1123      buf = i->iov_base;
1124      end_of_vec = i->iov_base + i->iov_len;
1125  
1126      for (written = 0; written < size; ) {
1127          size_t request_write_size;
1128      again:
1129          /*
1130           * Avoid too large data packets, as libssh currently does not
1131           * handle multiple requests on its own.
1132           */
1133          request_write_size = MIN(end_of_vec - buf, 131072);
1134          trace_ssh_write_buf(buf, end_of_vec - buf, request_write_size);
1135          r = sftp_write(s->sftp_handle, buf, request_write_size);
1136          trace_ssh_write_return(r, sftp_get_error(s->sftp));
1137  
1138          if (r == SSH_AGAIN) {
1139              co_yield(s, bs);
1140              goto again;
1141          }
1142          if (r < 0) {
1143              sftp_error_trace(s, "write");
1144              return -EIO;
1145          }
1146  
1147          written += r;
1148          buf += r;
1149          if (buf >= end_of_vec && written < size) {
1150              i++;
1151              buf = i->iov_base;
1152              end_of_vec = i->iov_base + i->iov_len;
1153          }
1154  
1155          if (offset + written > s->attrs->size) {
1156              s->attrs->size = offset + written;
1157          }
1158      }
1159  
1160      return 0;
1161  }
1162  
1163  static coroutine_fn int ssh_co_writev(BlockDriverState *bs,
1164                                        int64_t sector_num,
1165                                        int nb_sectors, QEMUIOVector *qiov,
1166                                        int flags)
1167  {
1168      BDRVSSHState *s = bs->opaque;
1169      int ret;
1170  
1171      assert(!flags);
1172      qemu_co_mutex_lock(&s->lock);
1173      ret = ssh_write(s, bs, sector_num * BDRV_SECTOR_SIZE,
1174                      nb_sectors * BDRV_SECTOR_SIZE, qiov);
1175      qemu_co_mutex_unlock(&s->lock);
1176  
1177      return ret;
1178  }
1179  
1180  static void unsafe_flush_warning(BDRVSSHState *s, const char *what)
1181  {
1182      if (!s->unsafe_flush_warning) {
1183          warn_report("ssh server %s does not support fsync",
1184                      s->inet->host);
1185          if (what) {
1186              error_report("to support fsync, you need %s", what);
1187          }
1188          s->unsafe_flush_warning = true;
1189      }
1190  }
1191  
1192  static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs)
1193  {
1194      int r;
1195  
1196      trace_ssh_flush();
1197  
1198      if (!sftp_extension_supported(s->sftp, "fsync@openssh.com", "1")) {
1199          unsafe_flush_warning(s, "OpenSSH >= 6.3");
1200          return 0;
1201      }
1202   again:
1203      r = sftp_fsync(s->sftp_handle);
1204      if (r == SSH_AGAIN) {
1205          co_yield(s, bs);
1206          goto again;
1207      }
1208      if (r < 0) {
1209          sftp_error_trace(s, "fsync");
1210          return -EIO;
1211      }
1212  
1213      return 0;
1214  }
1215  
1216  static coroutine_fn int ssh_co_flush(BlockDriverState *bs)
1217  {
1218      BDRVSSHState *s = bs->opaque;
1219      int ret;
1220  
1221      qemu_co_mutex_lock(&s->lock);
1222      ret = ssh_flush(s, bs);
1223      qemu_co_mutex_unlock(&s->lock);
1224  
1225      return ret;
1226  }
1227  
1228  static int64_t ssh_getlength(BlockDriverState *bs)
1229  {
1230      BDRVSSHState *s = bs->opaque;
1231      int64_t length;
1232  
1233      /* Note we cannot make a libssh call here. */
1234      length = (int64_t) s->attrs->size;
1235      trace_ssh_getlength(length);
1236  
1237      return length;
1238  }
1239  
1240  static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
1241                                          bool exact, PreallocMode prealloc,
1242                                          BdrvRequestFlags flags, Error **errp)
1243  {
1244      BDRVSSHState *s = bs->opaque;
1245  
1246      if (prealloc != PREALLOC_MODE_OFF) {
1247          error_setg(errp, "Unsupported preallocation mode '%s'",
1248                     PreallocMode_str(prealloc));
1249          return -ENOTSUP;
1250      }
1251  
1252      if (offset < s->attrs->size) {
1253          error_setg(errp, "ssh driver does not support shrinking files");
1254          return -ENOTSUP;
1255      }
1256  
1257      if (offset == s->attrs->size) {
1258          return 0;
1259      }
1260  
1261      return ssh_grow_file(s, offset, errp);
1262  }
1263  
1264  static void ssh_refresh_filename(BlockDriverState *bs)
1265  {
1266      BDRVSSHState *s = bs->opaque;
1267      const char *path, *host_key_check;
1268      int ret;
1269  
1270      /*
1271       * None of these options can be represented in a plain "host:port"
1272       * format, so if any was given, we have to abort.
1273       */
1274      if (s->inet->has_ipv4 || s->inet->has_ipv6 || s->inet->has_to ||
1275          s->inet->has_numeric)
1276      {
1277          return;
1278      }
1279  
1280      path = qdict_get_try_str(bs->full_open_options, "path");
1281      assert(path); /* mandatory option */
1282  
1283      host_key_check = qdict_get_try_str(bs->full_open_options, "host_key_check");
1284  
1285      ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
1286                     "ssh://%s@%s:%s%s%s%s",
1287                     s->user, s->inet->host, s->inet->port, path,
1288                     host_key_check ? "?host_key_check=" : "",
1289                     host_key_check ?: "");
1290      if (ret >= sizeof(bs->exact_filename)) {
1291          /* An overflow makes the filename unusable, so do not report any */
1292          bs->exact_filename[0] = '\0';
1293      }
1294  }
1295  
1296  static char *ssh_bdrv_dirname(BlockDriverState *bs, Error **errp)
1297  {
1298      if (qdict_haskey(bs->full_open_options, "host_key_check")) {
1299          /*
1300           * We cannot generate a simple prefix if we would have to
1301           * append a query string.
1302           */
1303          error_setg(errp,
1304                     "Cannot generate a base directory with host_key_check set");
1305          return NULL;
1306      }
1307  
1308      if (bs->exact_filename[0] == '\0') {
1309          error_setg(errp, "Cannot generate a base directory for this ssh node");
1310          return NULL;
1311      }
1312  
1313      return path_combine(bs->exact_filename, "");
1314  }
1315  
1316  static const char *const ssh_strong_runtime_opts[] = {
1317      "host",
1318      "port",
1319      "path",
1320      "user",
1321      "host_key_check",
1322      "server.",
1323  
1324      NULL
1325  };
1326  
1327  static BlockDriver bdrv_ssh = {
1328      .format_name                  = "ssh",
1329      .protocol_name                = "ssh",
1330      .instance_size                = sizeof(BDRVSSHState),
1331      .bdrv_parse_filename          = ssh_parse_filename,
1332      .bdrv_file_open               = ssh_file_open,
1333      .bdrv_co_create               = ssh_co_create,
1334      .bdrv_co_create_opts          = ssh_co_create_opts,
1335      .bdrv_close                   = ssh_close,
1336      .bdrv_has_zero_init           = ssh_has_zero_init,
1337      .bdrv_co_readv                = ssh_co_readv,
1338      .bdrv_co_writev               = ssh_co_writev,
1339      .bdrv_getlength               = ssh_getlength,
1340      .bdrv_co_truncate             = ssh_co_truncate,
1341      .bdrv_co_flush_to_disk        = ssh_co_flush,
1342      .bdrv_refresh_filename        = ssh_refresh_filename,
1343      .bdrv_dirname                 = ssh_bdrv_dirname,
1344      .create_opts                  = &ssh_create_opts,
1345      .strong_runtime_opts          = ssh_strong_runtime_opts,
1346  };
1347  
1348  static void bdrv_ssh_init(void)
1349  {
1350      int r;
1351  
1352      r = ssh_init();
1353      if (r != 0) {
1354          fprintf(stderr, "libssh initialization failed, %d\n", r);
1355          exit(EXIT_FAILURE);
1356      }
1357  
1358  #if TRACE_LIBSSH != 0
1359      ssh_set_log_level(TRACE_LIBSSH);
1360  #endif
1361  
1362      bdrv_register(&bdrv_ssh);
1363  }
1364  
1365  block_init(bdrv_ssh_init);
1366