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