Loading CHANGES +13 −6 Original line number Diff line number Diff line Loading @@ -6,19 +6,26 @@ Changelog Daniel Stenberg (23 Jul 2009) - Added CURLOPT_SSH_KNOWNHOSTS, CURLOPT_SSH_KEYFUNCTION, CURLOPT_SSH_KEYDATA. They introduce known_host support for SSH keys to libcurl. See docs for details. Note that this feature depends on a new enough libssh2 version, to be supported in libssh2 1.2 and later (or current git repo at this time). Michal Marek (22 Jul 2009) - David Binderman found a memory and fd leak in lib/gtls.c:load_file() (https://bugzilla.novell.com/523919). When looking at the code, I found that also the ptr pointer can leak. (https://bugzilla.novell.com/523919). When looking at the code, I found that also the ptr pointer can leak. Kamil Dudka (20 Jul 2009) - Claes Jakobsson improved the support for client certificates handling in NSS-powered libcurl. Now the client certificates can be selected - Claes Jakobsson improved the support for client certificates handling in NSS-powered libcurl. Now the client certificates can be selected automatically by a NSS built-in hook. Additionally pre-login to all PKCS11 slots is no more performed. It used to cause problems with HW tokens. - Fixed reference counting for NSS client certificates. Now the PEM reader module should be always properly unloaded on Curl_nss_cleanup(). If the unload fails though, libcurl will try to reuse the already loaded instance. module should be always properly unloaded on Curl_nss_cleanup(). If the unload fails though, libcurl will try to reuse the already loaded instance. Daniel Fandrich (15 Jul 2009) - Added nonblock.c to the non-automake makefiles (note that the dependencies Loading RELEASE-NOTES +2 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ Curl and libcurl 7.19.6 This release includes the following changes: o CURLOPT_FTPPORT (and curl's -P/--ftpport) support port ranges o Added CURLOPT_SSH_KNOWNHOSTS, CURLOPT_SSH_KEYFUNCTION, CURLOPT_SSH_KEYDATA This release includes the following bugfixes: Loading @@ -32,6 +33,7 @@ This release includes the following bugfixes: o curl -o - sends data to stdout using binary mode on windows o fixed the separators for "array" style string that CURLINFO_CERTINFO returns o auth problem over several hosts with re-used connection o improved the support for client certificates in libcurl+NSS o fix leak in gtls code This release includes the following known bugs: Loading docs/libcurl/curl_easy_setopt.3 +38 −0 Original line number Diff line number Diff line Loading @@ -1743,6 +1743,44 @@ Pass a char * pointing to a file name for your private key. If not used, libcurl defaults to using \fB~/.ssh/id_dsa\fP. If the file is password-protected, set the password with \fICURLOPT_KEYPASSWD\fP. (Added in 7.16.1) .IP CURLOPT_SSH_KNOWNHOSTS Pass a pointer to a zero terminated string holding the file name of the known_host file to use. The known_hosts file should use the OpenSSH file format as supported by libssh2. If this file is specified, libcurl will only accept connections with hosts that are known and present in that file, with a matching public key. Use \fICURLOPT_SSH_KEYFUNCTION\fP to alter the default behavior on host and key (mis)matching. (Added in 7.19.6) .IP CURLOPT_SSH_KEYFUNCTION Pass a pointer to a curl_sshkeycallback function. It gets called when the known_host matching has been done, to allow the application to act and decide for libcurl how to proceed. It gets passed the CURL handle, the key from the known_hosts file, the key from the remote site, info from libcurl on the matching status and a custom pointer (set with \fICURLOPT_SSH_KEYDATA\fP). It MUST return one of the following return codes to tell libcurl how to act: .RS .IP CURLKHSTAT_FINE_ADD_TO_FILE The host+key is accepted and libcurl will append it to the known_hosts file before continuing with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn't already present there. Note that the adding of data to the file is done by completely replacing the file with a new copy, so the permissions of the file must allow this. .IP CURLKHSTAT_FINE The host+key is accepted libcurl will continue with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn't already present there. .IP CURLKHSTAT_REJECT The host+key is rejected. libcurl will deny the connection to continue and it will be closed. .IP CURLKHSTAT_DEFER The host+key is rejected, but the SSH connection is asked to be kept alive. This feature could be used when the app wants to somehow return back and act on the host+key situation and then retry without needing the overhead of setting it up from scratch again. .RE (Added in 7.19.6) .IP CURLOPT_SSH_KEYDATA Pass a void * as parameter. This pointer will be passed along verbatim to the callback set with \fICURLOPT_SSH_KEYFUNCTION\fP. (Added in 7.19.6) .SH OTHER OPTIONS .IP CURLOPT_PRIVATE Pass a void * as parameter, pointing to data that should be associated with Loading include/curl/curl.h +49 −0 Original line number Diff line number Diff line Loading @@ -493,6 +493,45 @@ typedef enum { #define CURL_ERROR_SIZE 256 struct curl_khkey { const char *key; /* points to a zero-terminated string encoded with base64 if len is zero, otherwise to the "raw" data */ size_t len; enum type { CURLKHTYPE_UNKNOWN, CURLKHTYPE_RSA1, CURLKHTYPE_RSA, CURLKHTYPE_DSS } keytype; }; /* this is the set of return values expected from the curl_sshkeycallback callback */ enum curl_khstat { CURLKHSTAT_FINE_ADD_TO_FILE, CURLKHSTAT_FINE, CURLKHSTAT_REJECT, /* reject the connection, return an error */ CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so this causes a CURLE_DEFER error but otherwise the connection will be left intact etc */ CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ }; /* this is the set of status codes pass in to the callback */ enum curl_khmatch { CURLKHMATCH_OK, /* match */ CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ CURLKHMATCH_MISSING, /* no matching host/key found */ CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ }; typedef int (*curl_sshkeycallback) (CURL *easy, /* easy handle */ const struct curl_khkey *knownkey, /* known */ const struct curl_khkey *foundkey, /* found */ enum curl_khmatch, /* libcurl's view on the keys */ void *clientp); /* custom pointer passed from app */ /* parameter for the CURLOPT_USE_SSL option */ typedef enum { CURLUSESSL_NONE, /* do not attempt to use SSL */ Loading Loading @@ -1214,6 +1253,16 @@ typedef enum { to all protocols except FILE and SCP. */ CINIT(REDIR_PROTOCOLS, LONG, 182), /* set the SSH knownhost file name to use */ CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183), /* set the SSH host key callback, must point to a curl_sshkeycallback function */ CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184), /* set the SSH host key callback custom pointer */ CINIT(SSH_KEYDATA, OBJECTPOINT, 185), CURLOPT_LASTENTRY /* the last unused */ } CURLoption; Loading lib/ssh.c +154 −3 Original line number Diff line number Diff line Loading @@ -306,6 +306,7 @@ static void state(struct connectdata *conn, sshstate nowstate) static const char * const names[] = { "SSH_STOP", "SSH_S_STARTUP", "SSH_HOSTKEY", "SSH_AUTHLIST", "SSH_AUTH_PKEY_INIT", "SSH_AUTH_PKEY", Loading Loading @@ -433,6 +434,21 @@ static CURLcode ssh_getworkingpath(struct connectdata *conn, return CURLE_OK; } static int sshkeycallback(CURL *easy, const struct curl_khkey *knownkey, /* known */ const struct curl_khkey *foundkey, /* found */ enum curl_khmatch match, void *clientp) { (void)easy; (void)knownkey; (void)foundkey; (void)clientp; /* we only allow perfect matches, and we reject everything else */ return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE; } /* * Earlier libssh2 versions didn't have the ability to seek to 64bit positions * with 32bit size_t. Loading Loading @@ -483,9 +499,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) break; } /* Set libssh2 to non-blocking, since cURL is all non-blocking */ /* Set libssh2 to non-blocking, since everything internally is non-blocking */ libssh2_session_set_blocking(sshc->ssh_session, 0); state(conn, SSH_HOSTKEY); /* fall-through */ case SSH_HOSTKEY: #ifdef CURL_LIBSSH2_DEBUG /* * Before we authenticate we should check the hostkey's fingerprint Loading Loading @@ -527,12 +549,121 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } } #ifdef HAVE_LIBSSH2_KNOWNHOST_API if(data->set.str[STRING_SSH_KNOWNHOSTS]) { /* we're asked to verify the host against a file */ int keytype; size_t keylen; const char *remotekey = libssh2_session_hostkey(sshc->ssh_session, &keylen, &keytype); int keycheck; int keybit; if(remotekey) { /* * A subject to figure out is what host name we need to pass in here. * What host name does OpenSSH store in its file if an IDN name is * used? */ struct libssh2_knownhost *host; enum curl_khmatch keymatch; curl_sshkeycallback func = data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback; struct curl_khkey knownkey; struct curl_khkey *knownkeyp = NULL; struct curl_khkey foundkey; keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS; keycheck = libssh2_knownhost_check(sshc->kh, conn->host.name, remotekey, keylen, LIBSSH2_KNOWNHOST_TYPE_PLAIN| LIBSSH2_KNOWNHOST_KEYENC_RAW| keybit, &host); infof(data, "SSH host check: %d, key: %s\n", keycheck, (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)? host->key:"<none>"); /* setup 'knownkey' */ if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) { knownkey.key = host->key; knownkey.len = 0; knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? CURLKHTYPE_RSA : CURLKHTYPE_DSS; knownkeyp = &knownkey; } /* setup 'foundkey' */ foundkey.key = remotekey; foundkey.len = keylen; foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? CURLKHTYPE_RSA : CURLKHTYPE_DSS; /* * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the * curl_khmatch enum are ever modified, we need to introduce a * translation table here! */ keymatch = (enum curl_khmatch)keycheck; /* Ask the callback how to behave */ rc = func(data, knownkeyp, /* from the knownhosts file */ &foundkey, /* from the remote host */ keymatch, data->set.ssh_keyfunc_userp); } else /* no remotekey means failure! */ rc = CURLKHSTAT_REJECT; switch(rc) { default: /* unknown return codes will equal reject */ case CURLKHSTAT_REJECT: state(conn, SSH_SESSION_FREE); case CURLKHSTAT_DEFER: /* DEFER means bail out but keep the SSH_HOSTKEY state */ result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; break; case CURLKHSTAT_FINE: case CURLKHSTAT_FINE_ADD_TO_FILE: /* proceed */ if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) { /* the found host+key didn't match but has been told to be fine anyway so we add it in memory */ int addrc = libssh2_knownhost_add(sshc->kh, conn->host.name, NULL, remotekey, keylen, LIBSSH2_KNOWNHOST_TYPE_PLAIN| LIBSSH2_KNOWNHOST_KEYENC_RAW| keybit, NULL); if(addrc) infof(data, "Warning adding the known host %s failed!\n", conn->host.name); else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) { /* now we write the entire in-memory list of known hosts to the known_hosts file */ int wrc = libssh2_knownhost_writefile(sshc->kh, data->set.str[STRING_SSH_KNOWNHOSTS], LIBSSH2_KNOWNHOST_FILE_OPENSSH); if(wrc) { infof(data, "Warning, writing %s failed!\n", data->set.str[STRING_SSH_KNOWNHOSTS]); } } } break; } } #endif /* HAVE_LIBSSH2_KNOWNHOST_API */ state(conn, SSH_AUTHLIST); break; case SSH_AUTHLIST: /* TBD - methods to check the host keys need to be done */ /* * Figure out authentication methods * NB: As soon as we have provided a username to an openssh server we Loading Loading @@ -2278,6 +2409,26 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done) return CURLE_FAILED_INIT; } #ifdef HAVE_LIBSSH2_KNOWNHOST_API if(data->set.str[STRING_SSH_KNOWNHOSTS]) { int rc; ssh->kh = libssh2_knownhost_init(ssh->ssh_session); if(!ssh->kh) { /* eeek. TODO: free the ssh_session! */ return CURLE_FAILED_INIT; } /* read all known hosts from there */ rc = libssh2_knownhost_readfile(ssh->kh, data->set.str[STRING_SSH_KNOWNHOSTS], LIBSSH2_KNOWNHOST_FILE_OPENSSH); if(rc) { infof(data, "Failed to read known hosts from %s\n", data->set.str[STRING_SSH_KNOWNHOSTS]); } } #endif /* HAVE_LIBSSH2_KNOWNHOST_API */ #ifdef CURL_LIBSSH2_DEBUG libssh2_trace(ssh->ssh_session, ~0); infof(data, "SSH socket: %d\n", sock); Loading Loading
CHANGES +13 −6 Original line number Diff line number Diff line Loading @@ -6,19 +6,26 @@ Changelog Daniel Stenberg (23 Jul 2009) - Added CURLOPT_SSH_KNOWNHOSTS, CURLOPT_SSH_KEYFUNCTION, CURLOPT_SSH_KEYDATA. They introduce known_host support for SSH keys to libcurl. See docs for details. Note that this feature depends on a new enough libssh2 version, to be supported in libssh2 1.2 and later (or current git repo at this time). Michal Marek (22 Jul 2009) - David Binderman found a memory and fd leak in lib/gtls.c:load_file() (https://bugzilla.novell.com/523919). When looking at the code, I found that also the ptr pointer can leak. (https://bugzilla.novell.com/523919). When looking at the code, I found that also the ptr pointer can leak. Kamil Dudka (20 Jul 2009) - Claes Jakobsson improved the support for client certificates handling in NSS-powered libcurl. Now the client certificates can be selected - Claes Jakobsson improved the support for client certificates handling in NSS-powered libcurl. Now the client certificates can be selected automatically by a NSS built-in hook. Additionally pre-login to all PKCS11 slots is no more performed. It used to cause problems with HW tokens. - Fixed reference counting for NSS client certificates. Now the PEM reader module should be always properly unloaded on Curl_nss_cleanup(). If the unload fails though, libcurl will try to reuse the already loaded instance. module should be always properly unloaded on Curl_nss_cleanup(). If the unload fails though, libcurl will try to reuse the already loaded instance. Daniel Fandrich (15 Jul 2009) - Added nonblock.c to the non-automake makefiles (note that the dependencies Loading
RELEASE-NOTES +2 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ Curl and libcurl 7.19.6 This release includes the following changes: o CURLOPT_FTPPORT (and curl's -P/--ftpport) support port ranges o Added CURLOPT_SSH_KNOWNHOSTS, CURLOPT_SSH_KEYFUNCTION, CURLOPT_SSH_KEYDATA This release includes the following bugfixes: Loading @@ -32,6 +33,7 @@ This release includes the following bugfixes: o curl -o - sends data to stdout using binary mode on windows o fixed the separators for "array" style string that CURLINFO_CERTINFO returns o auth problem over several hosts with re-used connection o improved the support for client certificates in libcurl+NSS o fix leak in gtls code This release includes the following known bugs: Loading
docs/libcurl/curl_easy_setopt.3 +38 −0 Original line number Diff line number Diff line Loading @@ -1743,6 +1743,44 @@ Pass a char * pointing to a file name for your private key. If not used, libcurl defaults to using \fB~/.ssh/id_dsa\fP. If the file is password-protected, set the password with \fICURLOPT_KEYPASSWD\fP. (Added in 7.16.1) .IP CURLOPT_SSH_KNOWNHOSTS Pass a pointer to a zero terminated string holding the file name of the known_host file to use. The known_hosts file should use the OpenSSH file format as supported by libssh2. If this file is specified, libcurl will only accept connections with hosts that are known and present in that file, with a matching public key. Use \fICURLOPT_SSH_KEYFUNCTION\fP to alter the default behavior on host and key (mis)matching. (Added in 7.19.6) .IP CURLOPT_SSH_KEYFUNCTION Pass a pointer to a curl_sshkeycallback function. It gets called when the known_host matching has been done, to allow the application to act and decide for libcurl how to proceed. It gets passed the CURL handle, the key from the known_hosts file, the key from the remote site, info from libcurl on the matching status and a custom pointer (set with \fICURLOPT_SSH_KEYDATA\fP). It MUST return one of the following return codes to tell libcurl how to act: .RS .IP CURLKHSTAT_FINE_ADD_TO_FILE The host+key is accepted and libcurl will append it to the known_hosts file before continuing with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn't already present there. Note that the adding of data to the file is done by completely replacing the file with a new copy, so the permissions of the file must allow this. .IP CURLKHSTAT_FINE The host+key is accepted libcurl will continue with the connection. This will also add the host+key combo to the known_host pool kept in memory if it wasn't already present there. .IP CURLKHSTAT_REJECT The host+key is rejected. libcurl will deny the connection to continue and it will be closed. .IP CURLKHSTAT_DEFER The host+key is rejected, but the SSH connection is asked to be kept alive. This feature could be used when the app wants to somehow return back and act on the host+key situation and then retry without needing the overhead of setting it up from scratch again. .RE (Added in 7.19.6) .IP CURLOPT_SSH_KEYDATA Pass a void * as parameter. This pointer will be passed along verbatim to the callback set with \fICURLOPT_SSH_KEYFUNCTION\fP. (Added in 7.19.6) .SH OTHER OPTIONS .IP CURLOPT_PRIVATE Pass a void * as parameter, pointing to data that should be associated with Loading
include/curl/curl.h +49 −0 Original line number Diff line number Diff line Loading @@ -493,6 +493,45 @@ typedef enum { #define CURL_ERROR_SIZE 256 struct curl_khkey { const char *key; /* points to a zero-terminated string encoded with base64 if len is zero, otherwise to the "raw" data */ size_t len; enum type { CURLKHTYPE_UNKNOWN, CURLKHTYPE_RSA1, CURLKHTYPE_RSA, CURLKHTYPE_DSS } keytype; }; /* this is the set of return values expected from the curl_sshkeycallback callback */ enum curl_khstat { CURLKHSTAT_FINE_ADD_TO_FILE, CURLKHSTAT_FINE, CURLKHSTAT_REJECT, /* reject the connection, return an error */ CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so this causes a CURLE_DEFER error but otherwise the connection will be left intact etc */ CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ }; /* this is the set of status codes pass in to the callback */ enum curl_khmatch { CURLKHMATCH_OK, /* match */ CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ CURLKHMATCH_MISSING, /* no matching host/key found */ CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ }; typedef int (*curl_sshkeycallback) (CURL *easy, /* easy handle */ const struct curl_khkey *knownkey, /* known */ const struct curl_khkey *foundkey, /* found */ enum curl_khmatch, /* libcurl's view on the keys */ void *clientp); /* custom pointer passed from app */ /* parameter for the CURLOPT_USE_SSL option */ typedef enum { CURLUSESSL_NONE, /* do not attempt to use SSL */ Loading Loading @@ -1214,6 +1253,16 @@ typedef enum { to all protocols except FILE and SCP. */ CINIT(REDIR_PROTOCOLS, LONG, 182), /* set the SSH knownhost file name to use */ CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183), /* set the SSH host key callback, must point to a curl_sshkeycallback function */ CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184), /* set the SSH host key callback custom pointer */ CINIT(SSH_KEYDATA, OBJECTPOINT, 185), CURLOPT_LASTENTRY /* the last unused */ } CURLoption; Loading
lib/ssh.c +154 −3 Original line number Diff line number Diff line Loading @@ -306,6 +306,7 @@ static void state(struct connectdata *conn, sshstate nowstate) static const char * const names[] = { "SSH_STOP", "SSH_S_STARTUP", "SSH_HOSTKEY", "SSH_AUTHLIST", "SSH_AUTH_PKEY_INIT", "SSH_AUTH_PKEY", Loading Loading @@ -433,6 +434,21 @@ static CURLcode ssh_getworkingpath(struct connectdata *conn, return CURLE_OK; } static int sshkeycallback(CURL *easy, const struct curl_khkey *knownkey, /* known */ const struct curl_khkey *foundkey, /* found */ enum curl_khmatch match, void *clientp) { (void)easy; (void)knownkey; (void)foundkey; (void)clientp; /* we only allow perfect matches, and we reject everything else */ return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE; } /* * Earlier libssh2 versions didn't have the ability to seek to 64bit positions * with 32bit size_t. Loading Loading @@ -483,9 +499,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) break; } /* Set libssh2 to non-blocking, since cURL is all non-blocking */ /* Set libssh2 to non-blocking, since everything internally is non-blocking */ libssh2_session_set_blocking(sshc->ssh_session, 0); state(conn, SSH_HOSTKEY); /* fall-through */ case SSH_HOSTKEY: #ifdef CURL_LIBSSH2_DEBUG /* * Before we authenticate we should check the hostkey's fingerprint Loading Loading @@ -527,12 +549,121 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } } #ifdef HAVE_LIBSSH2_KNOWNHOST_API if(data->set.str[STRING_SSH_KNOWNHOSTS]) { /* we're asked to verify the host against a file */ int keytype; size_t keylen; const char *remotekey = libssh2_session_hostkey(sshc->ssh_session, &keylen, &keytype); int keycheck; int keybit; if(remotekey) { /* * A subject to figure out is what host name we need to pass in here. * What host name does OpenSSH store in its file if an IDN name is * used? */ struct libssh2_knownhost *host; enum curl_khmatch keymatch; curl_sshkeycallback func = data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback; struct curl_khkey knownkey; struct curl_khkey *knownkeyp = NULL; struct curl_khkey foundkey; keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS; keycheck = libssh2_knownhost_check(sshc->kh, conn->host.name, remotekey, keylen, LIBSSH2_KNOWNHOST_TYPE_PLAIN| LIBSSH2_KNOWNHOST_KEYENC_RAW| keybit, &host); infof(data, "SSH host check: %d, key: %s\n", keycheck, (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)? host->key:"<none>"); /* setup 'knownkey' */ if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) { knownkey.key = host->key; knownkey.len = 0; knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? CURLKHTYPE_RSA : CURLKHTYPE_DSS; knownkeyp = &knownkey; } /* setup 'foundkey' */ foundkey.key = remotekey; foundkey.len = keylen; foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? CURLKHTYPE_RSA : CURLKHTYPE_DSS; /* * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the * curl_khmatch enum are ever modified, we need to introduce a * translation table here! */ keymatch = (enum curl_khmatch)keycheck; /* Ask the callback how to behave */ rc = func(data, knownkeyp, /* from the knownhosts file */ &foundkey, /* from the remote host */ keymatch, data->set.ssh_keyfunc_userp); } else /* no remotekey means failure! */ rc = CURLKHSTAT_REJECT; switch(rc) { default: /* unknown return codes will equal reject */ case CURLKHSTAT_REJECT: state(conn, SSH_SESSION_FREE); case CURLKHSTAT_DEFER: /* DEFER means bail out but keep the SSH_HOSTKEY state */ result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; break; case CURLKHSTAT_FINE: case CURLKHSTAT_FINE_ADD_TO_FILE: /* proceed */ if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) { /* the found host+key didn't match but has been told to be fine anyway so we add it in memory */ int addrc = libssh2_knownhost_add(sshc->kh, conn->host.name, NULL, remotekey, keylen, LIBSSH2_KNOWNHOST_TYPE_PLAIN| LIBSSH2_KNOWNHOST_KEYENC_RAW| keybit, NULL); if(addrc) infof(data, "Warning adding the known host %s failed!\n", conn->host.name); else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) { /* now we write the entire in-memory list of known hosts to the known_hosts file */ int wrc = libssh2_knownhost_writefile(sshc->kh, data->set.str[STRING_SSH_KNOWNHOSTS], LIBSSH2_KNOWNHOST_FILE_OPENSSH); if(wrc) { infof(data, "Warning, writing %s failed!\n", data->set.str[STRING_SSH_KNOWNHOSTS]); } } } break; } } #endif /* HAVE_LIBSSH2_KNOWNHOST_API */ state(conn, SSH_AUTHLIST); break; case SSH_AUTHLIST: /* TBD - methods to check the host keys need to be done */ /* * Figure out authentication methods * NB: As soon as we have provided a username to an openssh server we Loading Loading @@ -2278,6 +2409,26 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done) return CURLE_FAILED_INIT; } #ifdef HAVE_LIBSSH2_KNOWNHOST_API if(data->set.str[STRING_SSH_KNOWNHOSTS]) { int rc; ssh->kh = libssh2_knownhost_init(ssh->ssh_session); if(!ssh->kh) { /* eeek. TODO: free the ssh_session! */ return CURLE_FAILED_INIT; } /* read all known hosts from there */ rc = libssh2_knownhost_readfile(ssh->kh, data->set.str[STRING_SSH_KNOWNHOSTS], LIBSSH2_KNOWNHOST_FILE_OPENSSH); if(rc) { infof(data, "Failed to read known hosts from %s\n", data->set.str[STRING_SSH_KNOWNHOSTS]); } } #endif /* HAVE_LIBSSH2_KNOWNHOST_API */ #ifdef CURL_LIBSSH2_DEBUG libssh2_trace(ssh->ssh_session, ~0); infof(data, "SSH socket: %d\n", sock); Loading