551
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
552
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
553
/* we're asked to verify the host against a file */
556
const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
563
* A subject to figure out is what host name we need to pass in here.
564
* What host name does OpenSSH store in its file if an IDN name is
567
struct libssh2_knownhost *host;
568
enum curl_khmatch keymatch;
569
curl_sshkeycallback func =
570
data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
571
struct curl_khkey knownkey;
572
struct curl_khkey *knownkeyp = NULL;
573
struct curl_khkey foundkey;
575
keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
576
LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS;
578
keycheck = libssh2_knownhost_check(sshc->kh,
581
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
582
LIBSSH2_KNOWNHOST_KEYENC_RAW|
586
infof(data, "SSH host check: %d, key: %s\n", keycheck,
587
(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
590
/* setup 'knownkey' */
591
if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
592
knownkey.key = host->key;
594
knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
595
CURLKHTYPE_RSA : CURLKHTYPE_DSS;
596
knownkeyp = &knownkey;
599
/* setup 'foundkey' */
600
foundkey.key = remotekey;
601
foundkey.len = keylen;
602
foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
603
CURLKHTYPE_RSA : CURLKHTYPE_DSS;
606
* if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
607
* curl_khmatch enum are ever modified, we need to introduce a
608
* translation table here!
610
keymatch = (enum curl_khmatch)keycheck;
612
/* Ask the callback how to behave */
613
rc = func(data, knownkeyp, /* from the knownhosts file */
614
&foundkey, /* from the remote host */
615
keymatch, data->set.ssh_keyfunc_userp);
618
/* no remotekey means failure! */
619
rc = CURLKHSTAT_REJECT;
622
default: /* unknown return codes will equal reject */
623
case CURLKHSTAT_REJECT:
624
state(conn, SSH_SESSION_FREE);
625
case CURLKHSTAT_DEFER:
626
/* DEFER means bail out but keep the SSH_HOSTKEY state */
627
result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
629
case CURLKHSTAT_FINE:
630
case CURLKHSTAT_FINE_ADD_TO_FILE:
632
if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
633
/* the found host+key didn't match but has been told to be fine
634
anyway so we add it in memory */
635
int addrc = libssh2_knownhost_add(sshc->kh,
636
conn->host.name, NULL,
638
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
639
LIBSSH2_KNOWNHOST_KEYENC_RAW|
642
infof(data, "Warning adding the known host %s failed!\n",
644
else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
645
/* now we write the entire in-memory list of known hosts to the
648
libssh2_knownhost_writefile(sshc->kh,
649
data->set.str[STRING_SSH_KNOWNHOSTS],
650
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
652
infof(data, "Warning, writing %s failed!\n",
653
data->set.str[STRING_SSH_KNOWNHOSTS]);
660
#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
530
662
state(conn, SSH_AUTHLIST);
533
665
case SSH_AUTHLIST:
534
/* TBD - methods to check the host keys need to be done */
537
667
* Figure out authentication methods
538
668
* NB: As soon as we have provided a username to an openssh server we
1950
2092
result = Curl_setup_transfer(conn, FIRSTSOCKET,
1951
2093
bytecount, FALSE, NULL, -1, NULL);
2095
/* not set by Curl_setup_transfer to preserve keepon bits */
2096
conn->writesockfd = conn->sockfd;
2098
/* FIXME: here should be explained why we need it to start the download */
2099
conn->cselect_bits = CURL_CSELECT_IN;
1954
2102
state(conn, SSH_SCP_CHANNEL_FREE);
1955
2103
sshc->actualcode = result;
2150
2306
struct ssh_conn *sshc = &conn->proto.sshc;
2152
if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
2310
else if((dir = libssh2_session_block_directions(sshc->ssh_session))) {
2153
2311
/* translate the libssh2 define bits into our own bit defines */
2154
sshc->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
2312
conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
2155
2313
((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
2158
2316
/* It didn't block or libssh2 didn't reveal in which direction, put back
2159
2317
the original set */
2160
sshc->waitfor = sshc->orig_waitfor;
2318
conn->waitfor = sshc->orig_waitfor;
2163
2321
/* no libssh2 directional support so we simply don't know */
2278
2436
return CURLE_FAILED_INIT;
2439
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
2440
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
2442
ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
2444
/* eeek. TODO: free the ssh_session! */
2445
return CURLE_FAILED_INIT;
2448
/* read all known hosts from there */
2449
rc = libssh2_knownhost_readfile(ssh->kh,
2450
data->set.str[STRING_SSH_KNOWNHOSTS],
2451
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
2453
infof(data, "Failed to read known hosts from %s\n",
2454
data->set.str[STRING_SSH_KNOWNHOSTS]);
2457
#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
2281
2459
#ifdef CURL_LIBSSH2_DEBUG
2282
2460
libssh2_trace(ssh->ssh_session, ~0);
2283
2461
infof(data, "SSH socket: %d\n", sock);