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