mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
- Added CURLOPT_SSH_KNOWNHOSTS, CURLOPT_SSH_KEYFUNCTION, CURLOPT_SSH_KEYDATA.
They introduce known_host support for SSH keys to libcurl. See docs for details.
This commit is contained in:
parent
9cff716925
commit
47c392e135
19
CHANGES
19
CHANGES
@ -6,19 +6,26 @@
|
|||||||
|
|
||||||
Changelog
|
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)
|
Michal Marek (22 Jul 2009)
|
||||||
- David Binderman found a memory and fd leak in lib/gtls.c:load_file()
|
- 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
|
(https://bugzilla.novell.com/523919). When looking at the code, I found that
|
||||||
that also the ptr pointer can leak.
|
also the ptr pointer can leak.
|
||||||
|
|
||||||
Kamil Dudka (20 Jul 2009)
|
Kamil Dudka (20 Jul 2009)
|
||||||
- Claes Jakobsson improved the support for client certificates handling
|
- Claes Jakobsson improved the support for client certificates handling in
|
||||||
in NSS-powered libcurl. Now the client certificates can be selected
|
NSS-powered libcurl. Now the client certificates can be selected
|
||||||
automatically by a NSS built-in hook. Additionally pre-login to all PKCS11
|
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.
|
slots is no more performed. It used to cause problems with HW tokens.
|
||||||
|
|
||||||
- Fixed reference counting for NSS client certificates. Now the PEM reader
|
- Fixed reference counting for NSS client certificates. Now the PEM reader
|
||||||
module should be always properly unloaded on Curl_nss_cleanup(). If the unload
|
module should be always properly unloaded on Curl_nss_cleanup(). If the
|
||||||
fails though, libcurl will try to reuse the already loaded instance.
|
unload fails though, libcurl will try to reuse the already loaded instance.
|
||||||
|
|
||||||
Daniel Fandrich (15 Jul 2009)
|
Daniel Fandrich (15 Jul 2009)
|
||||||
- Added nonblock.c to the non-automake makefiles (note that the dependencies
|
- Added nonblock.c to the non-automake makefiles (note that the dependencies
|
||||||
|
@ -10,6 +10,7 @@ Curl and libcurl 7.19.6
|
|||||||
This release includes the following changes:
|
This release includes the following changes:
|
||||||
|
|
||||||
o CURLOPT_FTPPORT (and curl's -P/--ftpport) support port ranges
|
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:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ This release includes the following bugfixes:
|
|||||||
o curl -o - sends data to stdout using binary mode on windows
|
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 fixed the separators for "array" style string that CURLINFO_CERTINFO returns
|
||||||
o auth problem over several hosts with re-used connection
|
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
|
o fix leak in gtls code
|
||||||
|
|
||||||
This release includes the following known bugs:
|
This release includes the following known bugs:
|
||||||
|
@ -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.
|
libcurl defaults to using \fB~/.ssh/id_dsa\fP.
|
||||||
If the file is password-protected, set the password with \fICURLOPT_KEYPASSWD\fP.
|
If the file is password-protected, set the password with \fICURLOPT_KEYPASSWD\fP.
|
||||||
(Added in 7.16.1)
|
(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
|
.SH OTHER OPTIONS
|
||||||
.IP CURLOPT_PRIVATE
|
.IP CURLOPT_PRIVATE
|
||||||
Pass a void * as parameter, pointing to data that should be associated with
|
Pass a void * as parameter, pointing to data that should be associated with
|
||||||
|
@ -493,6 +493,45 @@ typedef enum {
|
|||||||
|
|
||||||
#define CURL_ERROR_SIZE 256
|
#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 */
|
/* parameter for the CURLOPT_USE_SSL option */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CURLUSESSL_NONE, /* do not attempt to use SSL */
|
CURLUSESSL_NONE, /* do not attempt to use SSL */
|
||||||
@ -1214,6 +1253,16 @@ typedef enum {
|
|||||||
to all protocols except FILE and SCP. */
|
to all protocols except FILE and SCP. */
|
||||||
CINIT(REDIR_PROTOCOLS, LONG, 182),
|
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 */
|
CURLOPT_LASTENTRY /* the last unused */
|
||||||
} CURLoption;
|
} CURLoption;
|
||||||
|
|
||||||
|
157
lib/ssh.c
157
lib/ssh.c
@ -306,6 +306,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
|
|||||||
static const char * const names[] = {
|
static const char * const names[] = {
|
||||||
"SSH_STOP",
|
"SSH_STOP",
|
||||||
"SSH_S_STARTUP",
|
"SSH_S_STARTUP",
|
||||||
|
"SSH_HOSTKEY",
|
||||||
"SSH_AUTHLIST",
|
"SSH_AUTHLIST",
|
||||||
"SSH_AUTH_PKEY_INIT",
|
"SSH_AUTH_PKEY_INIT",
|
||||||
"SSH_AUTH_PKEY",
|
"SSH_AUTH_PKEY",
|
||||||
@ -433,6 +434,21 @@ static CURLcode ssh_getworkingpath(struct connectdata *conn,
|
|||||||
return CURLE_OK;
|
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
|
* Earlier libssh2 versions didn't have the ability to seek to 64bit positions
|
||||||
* with 32bit size_t.
|
* with 32bit size_t.
|
||||||
@ -483,9 +499,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
|||||||
break;
|
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);
|
libssh2_session_set_blocking(sshc->ssh_session, 0);
|
||||||
|
|
||||||
|
state(conn, SSH_HOSTKEY);
|
||||||
|
|
||||||
|
/* fall-through */
|
||||||
|
case SSH_HOSTKEY:
|
||||||
|
|
||||||
#ifdef CURL_LIBSSH2_DEBUG
|
#ifdef CURL_LIBSSH2_DEBUG
|
||||||
/*
|
/*
|
||||||
* Before we authenticate we should check the hostkey's fingerprint
|
* Before we authenticate we should check the hostkey's fingerprint
|
||||||
@ -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);
|
state(conn, SSH_AUTHLIST);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSH_AUTHLIST:
|
case SSH_AUTHLIST:
|
||||||
/* TBD - methods to check the host keys need to be done */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out authentication methods
|
* Figure out authentication methods
|
||||||
* NB: As soon as we have provided a username to an openssh server we
|
* NB: As soon as we have provided a username to an openssh server we
|
||||||
@ -2278,6 +2409,26 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
|
|||||||
return CURLE_FAILED_INIT;
|
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
|
#ifdef CURL_LIBSSH2_DEBUG
|
||||||
libssh2_trace(ssh->ssh_session, ~0);
|
libssh2_trace(ssh->ssh_session, ~0);
|
||||||
infof(data, "SSH socket: %d\n", sock);
|
infof(data, "SSH socket: %d\n", sock);
|
||||||
|
@ -172,7 +172,7 @@ curl_easy_strerror(CURLcode error)
|
|||||||
return "Malformed telnet option";
|
return "Malformed telnet option";
|
||||||
|
|
||||||
case CURLE_PEER_FAILED_VERIFICATION:
|
case CURLE_PEER_FAILED_VERIFICATION:
|
||||||
return "SSL peer certificate or SSH md5 fingerprint was not OK";
|
return "SSL peer certificate or SSH remote key was not OK";
|
||||||
|
|
||||||
case CURLE_GOT_NOTHING:
|
case CURLE_GOT_NOTHING:
|
||||||
return "Server returned nothing (no headers, no data)";
|
return "Server returned nothing (no headers, no data)";
|
||||||
|
27
lib/url.c
27
lib/url.c
@ -2169,6 +2169,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
data->set.ssl.sessionid = (bool)(0 != va_arg(param, long));
|
data->set.ssl.sessionid = (bool)(0 != va_arg(param, long));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef USE_LIBSSH2
|
||||||
|
/* we only include SSH options if explicitly built to support SSH */
|
||||||
case CURLOPT_SSH_AUTH_TYPES:
|
case CURLOPT_SSH_AUTH_TYPES:
|
||||||
data->set.ssh_auth_types = va_arg(param, long);
|
data->set.ssh_auth_types = va_arg(param, long);
|
||||||
break;
|
break;
|
||||||
@ -2196,6 +2198,31 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
result = setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
|
result = setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
|
||||||
va_arg(param, char *));
|
va_arg(param, char *));
|
||||||
break;
|
break;
|
||||||
|
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
|
||||||
|
case CURLOPT_SSH_KNOWNHOSTS:
|
||||||
|
/*
|
||||||
|
* Store the file name to read known hosts from.
|
||||||
|
*/
|
||||||
|
result = setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
|
||||||
|
va_arg(param, char *));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CURLOPT_SSH_KEYFUNCTION:
|
||||||
|
/* setting to NULL is fine since the ssh.c functions themselves will
|
||||||
|
then rever to use the internal default */
|
||||||
|
data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CURLOPT_SSH_KEYDATA:
|
||||||
|
/*
|
||||||
|
* Custom client data to pass to the SSH keyfunc callback
|
||||||
|
*/
|
||||||
|
data->set.ssh_keyfunc_userp = va_arg(param, void *);
|
||||||
|
break;
|
||||||
|
#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
|
||||||
|
|
||||||
|
#endif /* USE_LIBSSH2 */
|
||||||
|
|
||||||
case CURLOPT_HTTP_TRANSFER_DECODING:
|
case CURLOPT_HTTP_TRANSFER_DECODING:
|
||||||
/*
|
/*
|
||||||
* disable libcurl transfer encoding is used
|
* disable libcurl transfer encoding is used
|
||||||
|
@ -468,6 +468,7 @@ typedef enum {
|
|||||||
SSH_STOP = 0, /* do nothing state, stops the state machine */
|
SSH_STOP = 0, /* do nothing state, stops the state machine */
|
||||||
|
|
||||||
SSH_S_STARTUP, /* Session startup, First state in SSH-CONNECT */
|
SSH_S_STARTUP, /* Session startup, First state in SSH-CONNECT */
|
||||||
|
SSH_HOSTKEY, /* verify hostkey */
|
||||||
SSH_AUTHLIST,
|
SSH_AUTHLIST,
|
||||||
SSH_AUTH_PKEY_INIT,
|
SSH_AUTH_PKEY_INIT,
|
||||||
SSH_AUTH_PKEY,
|
SSH_AUTH_PKEY,
|
||||||
@ -566,6 +567,12 @@ struct ssh_conn {
|
|||||||
LIBSSH2_SFTP_HANDLE *sftp_handle;
|
LIBSSH2_SFTP_HANDLE *sftp_handle;
|
||||||
int waitfor; /* current READ/WRITE bits to wait for */
|
int waitfor; /* current READ/WRITE bits to wait for */
|
||||||
int orig_waitfor; /* default READ/WRITE bits wait for */
|
int orig_waitfor; /* default READ/WRITE bits wait for */
|
||||||
|
|
||||||
|
/* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h
|
||||||
|
header */
|
||||||
|
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
|
||||||
|
LIBSSH2_KNOWNHOSTS *kh;
|
||||||
|
#endif
|
||||||
#endif /* USE_LIBSSH2 */
|
#endif /* USE_LIBSSH2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1366,15 +1373,12 @@ enum dupstring {
|
|||||||
STRING_SET_RANGE, /* range, if used */
|
STRING_SET_RANGE, /* range, if used */
|
||||||
STRING_SET_REFERER, /* custom string for the HTTP referer field */
|
STRING_SET_REFERER, /* custom string for the HTTP referer field */
|
||||||
STRING_SET_URL, /* what original URL to work on */
|
STRING_SET_URL, /* what original URL to work on */
|
||||||
STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */
|
|
||||||
STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */
|
|
||||||
STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */
|
STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */
|
||||||
STRING_SSL_CAFILE, /* certificate file to verify peer against */
|
STRING_SSL_CAFILE, /* certificate file to verify peer against */
|
||||||
STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
|
STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
|
||||||
STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */
|
STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */
|
||||||
STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
|
STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
|
||||||
STRING_USERAGENT, /* User-Agent string */
|
STRING_USERAGENT, /* User-Agent string */
|
||||||
STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
|
|
||||||
STRING_SSL_CRLFILE, /* crl file to check certificate */
|
STRING_SSL_CRLFILE, /* crl file to check certificate */
|
||||||
STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
|
STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
|
||||||
STRING_USERNAME, /* <username>, if used */
|
STRING_USERNAME, /* <username>, if used */
|
||||||
@ -1383,6 +1387,12 @@ enum dupstring {
|
|||||||
STRING_PROXYPASSWORD, /* Proxy <password>, if used */
|
STRING_PROXYPASSWORD, /* Proxy <password>, if used */
|
||||||
STRING_NOPROXY, /* List of hosts which should not use the proxy, if
|
STRING_NOPROXY, /* List of hosts which should not use the proxy, if
|
||||||
used */
|
used */
|
||||||
|
#ifdef USE_LIBSSH2
|
||||||
|
STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */
|
||||||
|
STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */
|
||||||
|
STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
|
||||||
|
STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */
|
||||||
|
#endif
|
||||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||||
STRING_SOCKS5_GSSAPI_SERVICE, /* GSSAPI service name */
|
STRING_SOCKS5_GSSAPI_SERVICE, /* GSSAPI service name */
|
||||||
#endif
|
#endif
|
||||||
@ -1496,6 +1506,9 @@ struct UserDefined {
|
|||||||
2 - the same but also allow MKD to fail once
|
2 - the same but also allow MKD to fail once
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
curl_sshkeycallback ssh_keyfunc; /* key matching callback */
|
||||||
|
void *ssh_keyfunc_userp; /* custom pointer to callback */
|
||||||
|
|
||||||
/* Here follows boolean settings that define how to behave during
|
/* Here follows boolean settings that define how to behave during
|
||||||
this session. They are STATIC, set by libcurl users or at least initially
|
this session. They are STATIC, set by libcurl users or at least initially
|
||||||
and they don't change during operations. */
|
and they don't change during operations. */
|
||||||
|
10
src/main.c
10
src/main.c
@ -4694,6 +4694,16 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
my_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
|
my_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||||
my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1);
|
my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
char *home = homedir();
|
||||||
|
char *file = aprintf("%s/%sssh/known_hosts", home, DOT_CHAR);
|
||||||
|
if(home && file) {
|
||||||
|
free(home);
|
||||||
|
my_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
if(config->no_body || config->remote_time) {
|
if(config->no_body || config->remote_time) {
|
||||||
/* no body or use remote time */
|
/* no body or use remote time */
|
||||||
|
Loading…
Reference in New Issue
Block a user