Statistics
| Branch: | Revision:

root / block / ssh.c @ 56d1b4d2

History | View | Annotate | Download (28.7 kB)

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
/* Wrappers around error_report which make sure to dump as much
110
 * information from libssh2 as possible.
111
 */
112
static void GCC_FMT_ATTR(2, 3)
113
session_error_report(BDRVSSHState *s, const char *fs, ...)
114
{
115
    va_list args;
116

    
117
    va_start(args, fs);
118
    error_vprintf(fs, args);
119

    
120
    if ((s)->session) {
121
        char *ssh_err;
122
        int ssh_err_code;
123

    
124
        libssh2_session_last_error((s)->session, &ssh_err, NULL, 0);
125
        /* This is not an errno.  See <libssh2.h>. */
126
        ssh_err_code = libssh2_session_last_errno((s)->session);
127

    
128
        error_printf(": %s (libssh2 error code: %d)", ssh_err, ssh_err_code);
129
    }
130

    
131
    va_end(args);
132
    error_printf("\n");
133
}
134

    
135
static void GCC_FMT_ATTR(2, 3)
136
sftp_error_report(BDRVSSHState *s, const char *fs, ...)
137
{
138
    va_list args;
139

    
140
    va_start(args, fs);
141
    error_vprintf(fs, args);
142

    
143
    if ((s)->sftp) {
144
        char *ssh_err;
145
        int ssh_err_code;
146
        unsigned long sftp_err_code;
147

    
148
        libssh2_session_last_error((s)->session, &ssh_err, NULL, 0);
149
        /* This is not an errno.  See <libssh2.h>. */
150
        ssh_err_code = libssh2_session_last_errno((s)->session);
151
        /* See <libssh2_sftp.h>. */
152
        sftp_err_code = libssh2_sftp_last_error((s)->sftp);
153

    
154
        error_printf(": %s (libssh2 error code: %d, sftp error code: %lu)",
155
                     ssh_err, ssh_err_code, sftp_err_code);
156
    }
157

    
158
    va_end(args);
159
    error_printf("\n");
160
}
161

    
162
static int parse_uri(const char *filename, QDict *options, Error **errp)
163
{
164
    URI *uri = NULL;
165
    QueryParams *qp = NULL;
166
    int i;
167

    
168
    uri = uri_parse(filename);
169
    if (!uri) {
170
        return -EINVAL;
171
    }
172

    
173
    if (strcmp(uri->scheme, "ssh") != 0) {
174
        error_setg(errp, "URI scheme must be 'ssh'");
175
        goto err;
176
    }
177

    
178
    if (!uri->server || strcmp(uri->server, "") == 0) {
179
        error_setg(errp, "missing hostname in URI");
180
        goto err;
181
    }
182

    
183
    if (!uri->path || strcmp(uri->path, "") == 0) {
184
        error_setg(errp, "missing remote path in URI");
185
        goto err;
186
    }
187

    
188
    qp = query_params_parse(uri->query);
189
    if (!qp) {
190
        error_setg(errp, "could not parse query parameters");
191
        goto err;
192
    }
193

    
194
    if(uri->user && strcmp(uri->user, "") != 0) {
195
        qdict_put(options, "user", qstring_from_str(uri->user));
196
    }
197

    
198
    qdict_put(options, "host", qstring_from_str(uri->server));
199

    
200
    if (uri->port) {
201
        qdict_put(options, "port", qint_from_int(uri->port));
202
    }
203

    
204
    qdict_put(options, "path", qstring_from_str(uri->path));
205

    
206
    /* Pick out any query parameters that we understand, and ignore
207
     * the rest.
208
     */
209
    for (i = 0; i < qp->n; ++i) {
210
        if (strcmp(qp->p[i].name, "host_key_check") == 0) {
211
            qdict_put(options, "host_key_check",
212
                      qstring_from_str(qp->p[i].value));
213
        }
214
    }
215

    
216
    query_params_free(qp);
217
    uri_free(uri);
218
    return 0;
219

    
220
 err:
221
    if (qp) {
222
      query_params_free(qp);
223
    }
224
    if (uri) {
225
      uri_free(uri);
226
    }
227
    return -EINVAL;
228
}
229

    
230
static void ssh_parse_filename(const char *filename, QDict *options,
231
                               Error **errp)
232
{
233
    if (qdict_haskey(options, "user") ||
234
        qdict_haskey(options, "host") ||
235
        qdict_haskey(options, "port") ||
236
        qdict_haskey(options, "path") ||
237
        qdict_haskey(options, "host_key_check")) {
238
        error_setg(errp, "user, host, port, path, host_key_check cannot be used at the same time as a file option");
239
        return;
240
    }
241

    
242
    parse_uri(filename, options, errp);
243
}
244

    
245
static int check_host_key_knownhosts(BDRVSSHState *s,
246
                                     const char *host, int port)
247
{
248
    const char *home;
249
    char *knh_file = NULL;
250
    LIBSSH2_KNOWNHOSTS *knh = NULL;
251
    struct libssh2_knownhost *found;
252
    int ret, r;
253
    const char *hostkey;
254
    size_t len;
255
    int type;
256

    
257
    hostkey = libssh2_session_hostkey(s->session, &len, &type);
258
    if (!hostkey) {
259
        ret = -EINVAL;
260
        session_error_report(s, "failed to read remote host key");
261
        goto out;
262
    }
263

    
264
    knh = libssh2_knownhost_init(s->session);
265
    if (!knh) {
266
        ret = -EINVAL;
267
        session_error_report(s, "failed to initialize known hosts support");
268
        goto out;
269
    }
270

    
271
    home = getenv("HOME");
272
    if (home) {
273
        knh_file = g_strdup_printf("%s/.ssh/known_hosts", home);
274
    } else {
275
        knh_file = g_strdup_printf("/root/.ssh/known_hosts");
276
    }
277

    
278
    /* Read all known hosts from OpenSSH-style known_hosts file. */
279
    libssh2_knownhost_readfile(knh, knh_file, LIBSSH2_KNOWNHOST_FILE_OPENSSH);
280

    
281
    r = libssh2_knownhost_checkp(knh, host, port, hostkey, len,
282
                                 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
283
                                 LIBSSH2_KNOWNHOST_KEYENC_RAW,
284
                                 &found);
285
    switch (r) {
286
    case LIBSSH2_KNOWNHOST_CHECK_MATCH:
287
        /* OK */
288
        DPRINTF("host key OK: %s", found->key);
289
        break;
290
    case LIBSSH2_KNOWNHOST_CHECK_MISMATCH:
291
        ret = -EINVAL;
292
        session_error_report(s, "host key does not match the one in known_hosts (found key %s)",
293
                             found->key);
294
        goto out;
295
    case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND:
296
        ret = -EINVAL;
297
        session_error_report(s, "no host key was found in known_hosts");
298
        goto out;
299
    case LIBSSH2_KNOWNHOST_CHECK_FAILURE:
300
        ret = -EINVAL;
301
        session_error_report(s, "failure matching the host key with known_hosts");
302
        goto out;
303
    default:
304
        ret = -EINVAL;
305
        session_error_report(s, "unknown error matching the host key with known_hosts (%d)",
306
                             r);
307
        goto out;
308
    }
309

    
310
    /* known_hosts checking successful. */
311
    ret = 0;
312

    
313
 out:
314
    if (knh != NULL) {
315
        libssh2_knownhost_free(knh);
316
    }
317
    g_free(knh_file);
318
    return ret;
319
}
320

    
321
static unsigned hex2decimal(char ch)
322
{
323
    if (ch >= '0' && ch <= '9') {
324
        return (ch - '0');
325
    } else if (ch >= 'a' && ch <= 'f') {
326
        return 10 + (ch - 'a');
327
    } else if (ch >= 'A' && ch <= 'F') {
328
        return 10 + (ch - 'A');
329
    }
330

    
331
    return -1;
332
}
333

    
334
/* Compare the binary fingerprint (hash of host key) with the
335
 * host_key_check parameter.
336
 */
337
static int compare_fingerprint(const unsigned char *fingerprint, size_t len,
338
                               const char *host_key_check)
339
{
340
    unsigned c;
341

    
342
    while (len > 0) {
343
        while (*host_key_check == ':')
344
            host_key_check++;
345
        if (!qemu_isxdigit(host_key_check[0]) ||
346
            !qemu_isxdigit(host_key_check[1]))
347
            return 1;
348
        c = hex2decimal(host_key_check[0]) * 16 +
349
            hex2decimal(host_key_check[1]);
350
        if (c - *fingerprint != 0)
351
            return c - *fingerprint;
352
        fingerprint++;
353
        len--;
354
        host_key_check += 2;
355
    }
356
    return *host_key_check - '\0';
357
}
358

    
359
static int
360
check_host_key_hash(BDRVSSHState *s, const char *hash,
361
                    int hash_type, size_t fingerprint_len)
362
{
363
    const char *fingerprint;
364

    
365
    fingerprint = libssh2_hostkey_hash(s->session, hash_type);
366
    if (!fingerprint) {
367
        session_error_report(s, "failed to read remote host key");
368
        return -EINVAL;
369
    }
370

    
371
    if(compare_fingerprint((unsigned char *) fingerprint, fingerprint_len,
372
                           hash) != 0) {
373
        error_report("remote host key does not match host_key_check '%s'",
374
                     hash);
375
        return -EPERM;
376
    }
377

    
378
    return 0;
379
}
380

    
381
static int check_host_key(BDRVSSHState *s, const char *host, int port,
382
                          const char *host_key_check)
383
{
384
    /* host_key_check=no */
385
    if (strcmp(host_key_check, "no") == 0) {
386
        return 0;
387
    }
388

    
389
    /* host_key_check=md5:xx:yy:zz:... */
390
    if (strncmp(host_key_check, "md5:", 4) == 0) {
391
        return check_host_key_hash(s, &host_key_check[4],
392
                                   LIBSSH2_HOSTKEY_HASH_MD5, 16);
393
    }
394

    
395
    /* host_key_check=sha1:xx:yy:zz:... */
396
    if (strncmp(host_key_check, "sha1:", 5) == 0) {
397
        return check_host_key_hash(s, &host_key_check[5],
398
                                   LIBSSH2_HOSTKEY_HASH_SHA1, 20);
399
    }
400

    
401
    /* host_key_check=yes */
402
    if (strcmp(host_key_check, "yes") == 0) {
403
        return check_host_key_knownhosts(s, host, port);
404
    }
405

    
406
    error_report("unknown host_key_check setting (%s)", host_key_check);
407
    return -EINVAL;
408
}
409

    
410
static int authenticate(BDRVSSHState *s, const char *user)
411
{
412
    int r, ret;
413
    const char *userauthlist;
414
    LIBSSH2_AGENT *agent = NULL;
415
    struct libssh2_agent_publickey *identity;
416
    struct libssh2_agent_publickey *prev_identity = NULL;
417

    
418
    userauthlist = libssh2_userauth_list(s->session, user, strlen(user));
419
    if (strstr(userauthlist, "publickey") == NULL) {
420
        ret = -EPERM;
421
        error_report("remote server does not support \"publickey\" authentication");
422
        goto out;
423
    }
424

    
425
    /* Connect to ssh-agent and try each identity in turn. */
426
    agent = libssh2_agent_init(s->session);
427
    if (!agent) {
428
        ret = -EINVAL;
429
        session_error_report(s, "failed to initialize ssh-agent support");
430
        goto out;
431
    }
432
    if (libssh2_agent_connect(agent)) {
433
        ret = -ECONNREFUSED;
434
        session_error_report(s, "failed to connect to ssh-agent");
435
        goto out;
436
    }
437
    if (libssh2_agent_list_identities(agent)) {
438
        ret = -EINVAL;
439
        session_error_report(s, "failed requesting identities from ssh-agent");
440
        goto out;
441
    }
442

    
443
    for(;;) {
444
        r = libssh2_agent_get_identity(agent, &identity, prev_identity);
445
        if (r == 1) {           /* end of list */
446
            break;
447
        }
448
        if (r < 0) {
449
            ret = -EINVAL;
450
            session_error_report(s, "failed to obtain identity from ssh-agent");
451
            goto out;
452
        }
453
        r = libssh2_agent_userauth(agent, user, identity);
454
        if (r == 0) {
455
            /* Authenticated! */
456
            ret = 0;
457
            goto out;
458
        }
459
        /* Failed to authenticate with this identity, try the next one. */
460
        prev_identity = identity;
461
    }
462

    
463
    ret = -EPERM;
464
    error_report("failed to authenticate using publickey authentication "
465
                 "and the identities held by your ssh-agent");
466

    
467
 out:
468
    if (agent != NULL) {
469
        /* Note: libssh2 implementation implicitly calls
470
         * libssh2_agent_disconnect if necessary.
471
         */
472
        libssh2_agent_free(agent);
473
    }
474

    
475
    return ret;
476
}
477

    
478
static int connect_to_ssh(BDRVSSHState *s, QDict *options,
479
                          int ssh_flags, int creat_mode)
480
{
481
    int r, ret;
482
    Error *err = NULL;
483
    const char *host, *user, *path, *host_key_check;
484
    int port;
485

    
486
    host = qdict_get_str(options, "host");
487

    
488
    if (qdict_haskey(options, "port")) {
489
        port = qdict_get_int(options, "port");
490
    } else {
491
        port = 22;
492
    }
493

    
494
    path = qdict_get_str(options, "path");
495

    
496
    if (qdict_haskey(options, "user")) {
497
        user = qdict_get_str(options, "user");
498
    } else {
499
        user = g_get_user_name();
500
        if (!user) {
501
            ret = -errno;
502
            goto err;
503
        }
504
    }
505

    
506
    if (qdict_haskey(options, "host_key_check")) {
507
        host_key_check = qdict_get_str(options, "host_key_check");
508
    } else {
509
        host_key_check = "yes";
510
    }
511

    
512
    /* Construct the host:port name for inet_connect. */
513
    g_free(s->hostport);
514
    s->hostport = g_strdup_printf("%s:%d", host, port);
515

    
516
    /* Open the socket and connect. */
517
    s->sock = inet_connect(s->hostport, &err);
518
    if (err != NULL) {
519
        ret = -errno;
520
        qerror_report_err(err);
521
        error_free(err);
522
        goto err;
523
    }
524

    
525
    /* Create SSH session. */
526
    s->session = libssh2_session_init();
527
    if (!s->session) {
528
        ret = -EINVAL;
529
        session_error_report(s, "failed to initialize libssh2 session");
530
        goto err;
531
    }
532

    
533
#if TRACE_LIBSSH2 != 0
534
    libssh2_trace(s->session, TRACE_LIBSSH2);
535
#endif
536

    
537
    r = libssh2_session_handshake(s->session, s->sock);
538
    if (r != 0) {
539
        ret = -EINVAL;
540
        session_error_report(s, "failed to establish SSH session");
541
        goto err;
542
    }
543

    
544
    /* Check the remote host's key against known_hosts. */
545
    ret = check_host_key(s, host, port, host_key_check);
546
    if (ret < 0) {
547
        goto err;
548
    }
549

    
550
    /* Authenticate. */
551
    ret = authenticate(s, user);
552
    if (ret < 0) {
553
        goto err;
554
    }
555

    
556
    /* Start SFTP. */
557
    s->sftp = libssh2_sftp_init(s->session);
558
    if (!s->sftp) {
559
        session_error_report(s, "failed to initialize sftp handle");
560
        ret = -EINVAL;
561
        goto err;
562
    }
563

    
564
    /* Open the remote file. */
565
    DPRINTF("opening file %s flags=0x%x creat_mode=0%o",
566
            path, ssh_flags, creat_mode);
567
    s->sftp_handle = libssh2_sftp_open(s->sftp, path, ssh_flags, creat_mode);
568
    if (!s->sftp_handle) {
569
        session_error_report(s, "failed to open remote file '%s'", path);
570
        ret = -EINVAL;
571
        goto err;
572
    }
573

    
574
    r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs);
575
    if (r < 0) {
576
        sftp_error_report(s, "failed to read file attributes");
577
        return -EINVAL;
578
    }
579

    
580
    /* Delete the options we've used; any not deleted will cause the
581
     * block layer to give an error about unused options.
582
     */
583
    qdict_del(options, "host");
584
    qdict_del(options, "port");
585
    qdict_del(options, "user");
586
    qdict_del(options, "path");
587
    qdict_del(options, "host_key_check");
588

    
589
    return 0;
590

    
591
 err:
592
    if (s->sftp_handle) {
593
        libssh2_sftp_close(s->sftp_handle);
594
    }
595
    s->sftp_handle = NULL;
596
    if (s->sftp) {
597
        libssh2_sftp_shutdown(s->sftp);
598
    }
599
    s->sftp = NULL;
600
    if (s->session) {
601
        libssh2_session_disconnect(s->session,
602
                                   "from qemu ssh client: "
603
                                   "error opening connection");
604
        libssh2_session_free(s->session);
605
    }
606
    s->session = NULL;
607

    
608
    return ret;
609
}
610

    
611
static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags)
612
{
613
    BDRVSSHState *s = bs->opaque;
614
    int ret;
615
    int ssh_flags;
616

    
617
    ssh_state_init(s);
618

    
619
    ssh_flags = LIBSSH2_FXF_READ;
620
    if (bdrv_flags & BDRV_O_RDWR) {
621
        ssh_flags |= LIBSSH2_FXF_WRITE;
622
    }
623

    
624
    /* Start up SSH. */
625
    ret = connect_to_ssh(s, options, ssh_flags, 0);
626
    if (ret < 0) {
627
        goto err;
628
    }
629

    
630
    /* Go non-blocking. */
631
    libssh2_session_set_blocking(s->session, 0);
632

    
633
    return 0;
634

    
635
 err:
636
    if (s->sock >= 0) {
637
        close(s->sock);
638
    }
639
    s->sock = -1;
640

    
641
    return ret;
642
}
643

    
644
static QEMUOptionParameter ssh_create_options[] = {
645
    {
646
        .name = BLOCK_OPT_SIZE,
647
        .type = OPT_SIZE,
648
        .help = "Virtual disk size"
649
    },
650
    { NULL }
651
};
652

    
653
static int ssh_create(const char *filename, QEMUOptionParameter *options)
654
{
655
    int r, ret;
656
    Error *local_err = NULL;
657
    int64_t total_size = 0;
658
    QDict *uri_options = NULL;
659
    BDRVSSHState s;
660
    ssize_t r2;
661
    char c[1] = { '\0' };
662

    
663
    ssh_state_init(&s);
664

    
665
    /* Get desired file size. */
666
    while (options && options->name) {
667
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
668
            total_size = options->value.n;
669
        }
670
        options++;
671
    }
672
    DPRINTF("total_size=%" PRIi64, total_size);
673

    
674
    uri_options = qdict_new();
675
    r = parse_uri(filename, uri_options, &local_err);
676
    if (r < 0) {
677
        qerror_report_err(local_err);
678
        error_free(local_err);
679
        ret = r;
680
        goto out;
681
    }
682

    
683
    r = connect_to_ssh(&s, uri_options,
684
                       LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE|
685
                       LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, 0644);
686
    if (r < 0) {
687
        ret = r;
688
        goto out;
689
    }
690

    
691
    if (total_size > 0) {
692
        libssh2_sftp_seek64(s.sftp_handle, total_size-1);
693
        r2 = libssh2_sftp_write(s.sftp_handle, c, 1);
694
        if (r2 < 0) {
695
            sftp_error_report(&s, "truncate failed");
696
            ret = -EINVAL;
697
            goto out;
698
        }
699
        s.attrs.filesize = total_size;
700
    }
701

    
702
    ret = 0;
703

    
704
 out:
705
    ssh_state_free(&s);
706
    if (uri_options != NULL) {
707
        QDECREF(uri_options);
708
    }
709
    return ret;
710
}
711

    
712
static void ssh_close(BlockDriverState *bs)
713
{
714
    BDRVSSHState *s = bs->opaque;
715

    
716
    ssh_state_free(s);
717
}
718

    
719
static void restart_coroutine(void *opaque)
720
{
721
    Coroutine *co = opaque;
722

    
723
    DPRINTF("co=%p", co);
724

    
725
    qemu_coroutine_enter(co, NULL);
726
}
727

    
728
/* Always true because when we have called set_fd_handler there is
729
 * always a request being processed.
730
 */
731
static int return_true(void *opaque)
732
{
733
    return 1;
734
}
735

    
736
static coroutine_fn void set_fd_handler(BDRVSSHState *s)
737
{
738
    int r;
739
    IOHandler *rd_handler = NULL, *wr_handler = NULL;
740
    Coroutine *co = qemu_coroutine_self();
741

    
742
    r = libssh2_session_block_directions(s->session);
743

    
744
    if (r & LIBSSH2_SESSION_BLOCK_INBOUND) {
745
        rd_handler = restart_coroutine;
746
    }
747
    if (r & LIBSSH2_SESSION_BLOCK_OUTBOUND) {
748
        wr_handler = restart_coroutine;
749
    }
750

    
751
    DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s->sock,
752
            rd_handler, wr_handler);
753

    
754
    qemu_aio_set_fd_handler(s->sock, rd_handler, wr_handler, return_true, co);
755
}
756

    
757
static coroutine_fn void clear_fd_handler(BDRVSSHState *s)
758
{
759
    DPRINTF("s->sock=%d", s->sock);
760
    qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL, NULL);
761
}
762

    
763
/* A non-blocking call returned EAGAIN, so yield, ensuring the
764
 * handlers are set up so that we'll be rescheduled when there is an
765
 * interesting event on the socket.
766
 */
767
static coroutine_fn void co_yield(BDRVSSHState *s)
768
{
769
    set_fd_handler(s);
770
    qemu_coroutine_yield();
771
    clear_fd_handler(s);
772
}
773

    
774
/* SFTP has a function `libssh2_sftp_seek64' which seeks to a position
775
 * in the remote file.  Notice that it just updates a field in the
776
 * sftp_handle structure, so there is no network traffic and it cannot
777
 * fail.
778
 *
779
 * However, `libssh2_sftp_seek64' does have a catastrophic effect on
780
 * performance since it causes the handle to throw away all in-flight
781
 * reads and buffered readahead data.  Therefore this function tries
782
 * to be intelligent about when to call the underlying libssh2 function.
783
 */
784
#define SSH_SEEK_WRITE 0
785
#define SSH_SEEK_READ  1
786
#define SSH_SEEK_FORCE 2
787

    
788
static void ssh_seek(BDRVSSHState *s, int64_t offset, int flags)
789
{
790
    bool op_read = (flags & SSH_SEEK_READ) != 0;
791
    bool force = (flags & SSH_SEEK_FORCE) != 0;
792

    
793
    if (force || op_read != s->offset_op_read || offset != s->offset) {
794
        DPRINTF("seeking to offset=%" PRIi64, offset);
795
        libssh2_sftp_seek64(s->sftp_handle, offset);
796
        s->offset = offset;
797
        s->offset_op_read = op_read;
798
    }
799
}
800

    
801
static coroutine_fn int ssh_read(BDRVSSHState *s,
802
                                 int64_t offset, size_t size,
803
                                 QEMUIOVector *qiov)
804
{
805
    ssize_t r;
806
    size_t got;
807
    char *buf, *end_of_vec;
808
    struct iovec *i;
809

    
810
    DPRINTF("offset=%" PRIi64 " size=%zu", offset, size);
811

    
812
    ssh_seek(s, offset, SSH_SEEK_READ);
813

    
814
    /* This keeps track of the current iovec element ('i'), where we
815
     * will write to next ('buf'), and the end of the current iovec
816
     * ('end_of_vec').
817
     */
818
    i = &qiov->iov[0];
819
    buf = i->iov_base;
820
    end_of_vec = i->iov_base + i->iov_len;
821

    
822
    /* libssh2 has a hard-coded limit of 2000 bytes per request,
823
     * although it will also do readahead behind our backs.  Therefore
824
     * we may have to do repeated reads here until we have read 'size'
825
     * bytes.
826
     */
827
    for (got = 0; got < size; ) {
828
    again:
829
        DPRINTF("sftp_read buf=%p size=%zu", buf, end_of_vec - buf);
830
        r = libssh2_sftp_read(s->sftp_handle, buf, end_of_vec - buf);
831
        DPRINTF("sftp_read returned %zd", r);
832

    
833
        if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
834
            co_yield(s);
835
            goto again;
836
        }
837
        if (r < 0) {
838
            sftp_error_report(s, "read failed");
839
            s->offset = -1;
840
            return -EIO;
841
        }
842
        if (r == 0) {
843
            /* EOF: Short read so pad the buffer with zeroes and return it. */
844
            qemu_iovec_memset(qiov, got, 0, size - got);
845
            return 0;
846
        }
847

    
848
        got += r;
849
        buf += r;
850
        s->offset += r;
851
        if (buf >= end_of_vec && got < size) {
852
            i++;
853
            buf = i->iov_base;
854
            end_of_vec = i->iov_base + i->iov_len;
855
        }
856
    }
857

    
858
    return 0;
859
}
860

    
861
static coroutine_fn int ssh_co_readv(BlockDriverState *bs,
862
                                     int64_t sector_num,
863
                                     int nb_sectors, QEMUIOVector *qiov)
864
{
865
    BDRVSSHState *s = bs->opaque;
866
    int ret;
867

    
868
    qemu_co_mutex_lock(&s->lock);
869
    ret = ssh_read(s, sector_num * BDRV_SECTOR_SIZE,
870
                   nb_sectors * BDRV_SECTOR_SIZE, qiov);
871
    qemu_co_mutex_unlock(&s->lock);
872

    
873
    return ret;
874
}
875

    
876
static int ssh_write(BDRVSSHState *s,
877
                     int64_t offset, size_t size,
878
                     QEMUIOVector *qiov)
879
{
880
    ssize_t r;
881
    size_t written;
882
    char *buf, *end_of_vec;
883
    struct iovec *i;
884

    
885
    DPRINTF("offset=%" PRIi64 " size=%zu", offset, size);
886

    
887
    ssh_seek(s, offset, SSH_SEEK_WRITE);
888

    
889
    /* This keeps track of the current iovec element ('i'), where we
890
     * will read from next ('buf'), and the end of the current iovec
891
     * ('end_of_vec').
892
     */
893
    i = &qiov->iov[0];
894
    buf = i->iov_base;
895
    end_of_vec = i->iov_base + i->iov_len;
896

    
897
    for (written = 0; written < size; ) {
898
    again:
899
        DPRINTF("sftp_write buf=%p size=%zu", buf, end_of_vec - buf);
900
        r = libssh2_sftp_write(s->sftp_handle, buf, end_of_vec - buf);
901
        DPRINTF("sftp_write returned %zd", r);
902

    
903
        if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
904
            co_yield(s);
905
            goto again;
906
        }
907
        if (r < 0) {
908
            sftp_error_report(s, "write failed");
909
            s->offset = -1;
910
            return -EIO;
911
        }
912
        /* The libssh2 API is very unclear about this.  A comment in
913
         * the code says "nothing was acked, and no EAGAIN was
914
         * received!" which apparently means that no data got sent
915
         * out, and the underlying channel didn't return any EAGAIN
916
         * indication.  I think this is a bug in either libssh2 or
917
         * OpenSSH (server-side).  In any case, forcing a seek (to
918
         * discard libssh2 internal buffers), and then trying again
919
         * works for me.
920
         */
921
        if (r == 0) {
922
            ssh_seek(s, offset + written, SSH_SEEK_WRITE|SSH_SEEK_FORCE);
923
            co_yield(s);
924
            goto again;
925
        }
926

    
927
        written += r;
928
        buf += r;
929
        s->offset += r;
930
        if (buf >= end_of_vec && written < size) {
931
            i++;
932
            buf = i->iov_base;
933
            end_of_vec = i->iov_base + i->iov_len;
934
        }
935

    
936
        if (offset + written > s->attrs.filesize)
937
            s->attrs.filesize = offset + written;
938
    }
939

    
940
    return 0;
941
}
942

    
943
static coroutine_fn int ssh_co_writev(BlockDriverState *bs,
944
                                      int64_t sector_num,
945
                                      int nb_sectors, QEMUIOVector *qiov)
946
{
947
    BDRVSSHState *s = bs->opaque;
948
    int ret;
949

    
950
    qemu_co_mutex_lock(&s->lock);
951
    ret = ssh_write(s, sector_num * BDRV_SECTOR_SIZE,
952
                    nb_sectors * BDRV_SECTOR_SIZE, qiov);
953
    qemu_co_mutex_unlock(&s->lock);
954

    
955
    return ret;
956
}
957

    
958
static void unsafe_flush_warning(BDRVSSHState *s, const char *what)
959
{
960
    if (!s->unsafe_flush_warning) {
961
        error_report("warning: ssh server %s does not support fsync",
962
                     s->hostport);
963
        if (what) {
964
            error_report("to support fsync, you need %s", what);
965
        }
966
        s->unsafe_flush_warning = true;
967
    }
968
}
969

    
970
#ifdef HAS_LIBSSH2_SFTP_FSYNC
971

    
972
static coroutine_fn int ssh_flush(BDRVSSHState *s)
973
{
974
    int r;
975

    
976
    DPRINTF("fsync");
977
 again:
978
    r = libssh2_sftp_fsync(s->sftp_handle);
979
    if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
980
        co_yield(s);
981
        goto again;
982
    }
983
    if (r == LIBSSH2_ERROR_SFTP_PROTOCOL &&
984
        libssh2_sftp_last_error(s->sftp) == LIBSSH2_FX_OP_UNSUPPORTED) {
985
        unsafe_flush_warning(s, "OpenSSH >= 6.3");
986
        return 0;
987
    }
988
    if (r < 0) {
989
        sftp_error_report(s, "fsync failed");
990
        return -EIO;
991
    }
992

    
993
    return 0;
994
}
995

    
996
static coroutine_fn int ssh_co_flush(BlockDriverState *bs)
997
{
998
    BDRVSSHState *s = bs->opaque;
999
    int ret;
1000

    
1001
    qemu_co_mutex_lock(&s->lock);
1002
    ret = ssh_flush(s);
1003
    qemu_co_mutex_unlock(&s->lock);
1004

    
1005
    return ret;
1006
}
1007

    
1008
#else /* !HAS_LIBSSH2_SFTP_FSYNC */
1009

    
1010
static coroutine_fn int ssh_co_flush(BlockDriverState *bs)
1011
{
1012
    BDRVSSHState *s = bs->opaque;
1013

    
1014
    unsafe_flush_warning(s, "libssh2 >= 1.4.4");
1015
    return 0;
1016
}
1017

    
1018
#endif /* !HAS_LIBSSH2_SFTP_FSYNC */
1019

    
1020
static int64_t ssh_getlength(BlockDriverState *bs)
1021
{
1022
    BDRVSSHState *s = bs->opaque;
1023
    int64_t length;
1024

    
1025
    /* Note we cannot make a libssh2 call here. */
1026
    length = (int64_t) s->attrs.filesize;
1027
    DPRINTF("length=%" PRIi64, length);
1028

    
1029
    return length;
1030
}
1031

    
1032
static BlockDriver bdrv_ssh = {
1033
    .format_name                  = "ssh",
1034
    .protocol_name                = "ssh",
1035
    .instance_size                = sizeof(BDRVSSHState),
1036
    .bdrv_parse_filename          = ssh_parse_filename,
1037
    .bdrv_file_open               = ssh_file_open,
1038
    .bdrv_create                  = ssh_create,
1039
    .bdrv_close                   = ssh_close,
1040
    .bdrv_co_readv                = ssh_co_readv,
1041
    .bdrv_co_writev               = ssh_co_writev,
1042
    .bdrv_getlength               = ssh_getlength,
1043
    .bdrv_co_flush_to_disk        = ssh_co_flush,
1044
    .create_options               = ssh_create_options,
1045
};
1046

    
1047
static void bdrv_ssh_init(void)
1048
{
1049
    int r;
1050

    
1051
    r = libssh2_init(0);
1052
    if (r != 0) {
1053
        fprintf(stderr, "libssh2 initialization failed, %d\n", r);
1054
        exit(EXIT_FAILURE);
1055
    }
1056

    
1057
    bdrv_register(&bdrv_ssh);
1058
}
1059

    
1060
block_init(bdrv_ssh_init);