mirror of
https://github.com/moparisthebest/curl
synced 2024-11-10 11:35:07 -05:00
Based on a patch brought by Johnny Luong, libcurl now offers
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 and the curl tool --hostpubmd5. They both make the SCP or SFTP connection verify the remote host's md5 checksum of the public key before doing a connect, to reduce the risk of a man-in-the-middle attack.
This commit is contained in:
parent
15b8da1980
commit
51c6a5d43b
7
CHANGES
7
CHANGES
@ -6,6 +6,13 @@
|
|||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
|
Daniel S (3 October 2007)
|
||||||
|
- Based on a patch brought by Johnny Luong, libcurl now offers
|
||||||
|
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 and the curl tool --hostpubmd5. They both
|
||||||
|
make the SCP or SFTP connection verify the remote host's md5 checksum of the
|
||||||
|
public key before doing a connect, to reduce the risk of a man-in-the-middle
|
||||||
|
attack.
|
||||||
|
|
||||||
Daniel S (2 October 2007)
|
Daniel S (2 October 2007)
|
||||||
- libcurl now handles chunked-encoded CONNECT responses
|
- libcurl now handles chunked-encoded CONNECT responses
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@ Curl and libcurl 7.17.1
|
|||||||
|
|
||||||
Public curl release number: 102
|
Public curl release number: 102
|
||||||
Releases counted from the very beginning: 128
|
Releases counted from the very beginning: 128
|
||||||
Available command line options: 120
|
Available command line options: 121
|
||||||
Available curl_easy_setopt() options: 144
|
Available curl_easy_setopt() options: 145
|
||||||
Number of public functions in libcurl: 55
|
Number of public functions in libcurl: 55
|
||||||
Amount of public web site mirrors: 42
|
Amount of public web site mirrors: 42
|
||||||
Number of known libcurl bindings: 36
|
Number of known libcurl bindings: 36
|
||||||
@ -16,6 +16,7 @@ This release includes the following changes:
|
|||||||
o added --proxy-negotiate
|
o added --proxy-negotiate
|
||||||
o added --post301 and CURLOPT_POST301
|
o added --post301 and CURLOPT_POST301
|
||||||
o builds with c-ares 1.5.0
|
o builds with c-ares 1.5.0
|
||||||
|
o added CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 and --hostpubmd5
|
||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
@ -47,6 +48,6 @@ This release would not have looked like this without help, code, reports and
|
|||||||
advice from friends like these:
|
advice from friends like these:
|
||||||
|
|
||||||
Dan Fandrich, Michal Marek, Günter Knauf, Rob Crittenden, Immanuel Gregoire,
|
Dan Fandrich, Michal Marek, Günter Knauf, Rob Crittenden, Immanuel Gregoire,
|
||||||
Mark Davies, Max Katsev, Philip Langdale, Alex Fishman
|
Mark Davies, Max Katsev, Philip Langdale, Alex Fishman, Johnny Luong
|
||||||
|
|
||||||
Thanks! (and sorry if I forgot to mention someone)
|
Thanks! (and sorry if I forgot to mention someone)
|
||||||
|
@ -544,6 +544,11 @@ for you.
|
|||||||
See also the \fI-A/--user-agent\fP and \fI-e/--referer\fP options.
|
See also the \fI-A/--user-agent\fP and \fI-e/--referer\fP options.
|
||||||
|
|
||||||
This option can be used multiple times to add/replace/remove multiple headers.
|
This option can be used multiple times to add/replace/remove multiple headers.
|
||||||
|
.IP "--hostpubmd5"
|
||||||
|
Pass a string containing 32 hexadecimal digits. The string should be the 128
|
||||||
|
bit MD5 cheksum of the remote host's public key, curl will refuse the
|
||||||
|
connection with the host unless the md5sums match. This option is only for SCP
|
||||||
|
and SFTP transfers. (Added in 7.17.1)
|
||||||
.IP "--ignore-content-length"
|
.IP "--ignore-content-length"
|
||||||
(HTTP)
|
(HTTP)
|
||||||
Ignore the Content-Length header. This is particularly useful for servers
|
Ignore the Content-Length header. This is particularly useful for servers
|
||||||
|
@ -1411,6 +1411,11 @@ Pass a long set to a bitmask consisting of one or more of
|
|||||||
CURLSSH_AUTH_PUBLICKEY, CURLSSH_AUTH_PASSWORD, CURLSSH_AUTH_HOST,
|
CURLSSH_AUTH_PUBLICKEY, CURLSSH_AUTH_PASSWORD, CURLSSH_AUTH_HOST,
|
||||||
CURLSSH_AUTH_KEYBOARD. Set CURLSSH_AUTH_ANY to let libcurl pick one.
|
CURLSSH_AUTH_KEYBOARD. Set CURLSSH_AUTH_ANY to let libcurl pick one.
|
||||||
(Added in 7.16.1)
|
(Added in 7.16.1)
|
||||||
|
.IP CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
|
||||||
|
Pass a char * pointing to a string containing 32 hexadecimal digits. The
|
||||||
|
string should be the 128 bit MD5 cheksum of the remote host's public key, and
|
||||||
|
libcurl will reject the connection to the host unless the md5sums match. This
|
||||||
|
option is only for SCP and SFTP transfers. (Added in 7.17.1)
|
||||||
.IP CURLOPT_SSH_PUBLIC_KEYFILE
|
.IP CURLOPT_SSH_PUBLIC_KEYFILE
|
||||||
Pass a char * pointing to a file name for your public key. If not used,
|
Pass a char * pointing to a file name for your public key. If not used,
|
||||||
libcurl defaults to using \fB~/.ssh/id_dsa.pub\fP.
|
libcurl defaults to using \fB~/.ssh/id_dsa.pub\fP.
|
||||||
|
@ -419,7 +419,7 @@ typedef enum {
|
|||||||
/* These are scheduled to disappear by 2009 */
|
/* These are scheduled to disappear by 2009 */
|
||||||
|
|
||||||
/* The following were added in 7.17.0 */
|
/* The following were added in 7.17.0 */
|
||||||
#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* noone should be using this! */
|
#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* noone should be using this! */
|
||||||
#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
|
#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
|
||||||
#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
|
#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
|
||||||
#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
|
#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
|
||||||
@ -438,7 +438,7 @@ typedef enum {
|
|||||||
#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
|
#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
|
||||||
#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
|
#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
|
||||||
#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
|
#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
|
||||||
#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
|
#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
|
||||||
#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
|
#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
|
||||||
|
|
||||||
/* The following were added earlier */
|
/* The following were added earlier */
|
||||||
@ -1127,6 +1127,9 @@ typedef enum {
|
|||||||
/* Obey RFC 2616/10.3.2 and keep POSTs as POSTs after a 301 */
|
/* Obey RFC 2616/10.3.2 and keep POSTs as POSTs after a 301 */
|
||||||
CINIT(POST301, LONG, 161),
|
CINIT(POST301, LONG, 161),
|
||||||
|
|
||||||
|
/* used by scp/sftp to verify the host's public key */
|
||||||
|
CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162),
|
||||||
|
|
||||||
CURLOPT_LASTENTRY /* the last unused */
|
CURLOPT_LASTENTRY /* the last unused */
|
||||||
} CURLoption;
|
} CURLoption;
|
||||||
|
|
||||||
@ -1137,7 +1140,7 @@ typedef enum {
|
|||||||
/* These are scheduled to disappear by 2009 */
|
/* These are scheduled to disappear by 2009 */
|
||||||
|
|
||||||
/* The following were added in 7.17.0 */
|
/* The following were added in 7.17.0 */
|
||||||
#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD
|
#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD
|
||||||
#define CURLOPT_FTPAPPEND CURLOPT_APPEND
|
#define CURLOPT_FTPAPPEND CURLOPT_APPEND
|
||||||
#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY
|
#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY
|
||||||
#define CURLOPT_FTP_SSL CURLOPT_USE_SSL
|
#define CURLOPT_FTP_SSL CURLOPT_USE_SSL
|
||||||
|
27
lib/ssh.c
27
lib/ssh.c
@ -310,7 +310,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
|
|||||||
#ifdef CURL_LIBSSH2_DEBUG
|
#ifdef CURL_LIBSSH2_DEBUG
|
||||||
const char *fingerprint;
|
const char *fingerprint;
|
||||||
#endif /* CURL_LIBSSH2_DEBUG */
|
#endif /* CURL_LIBSSH2_DEBUG */
|
||||||
int rc;
|
const char *host_public_key_md5;
|
||||||
|
int rc,i;
|
||||||
long err;
|
long err;
|
||||||
|
|
||||||
switch(sshc->state) {
|
switch(sshc->state) {
|
||||||
@ -351,6 +352,30 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
|
|||||||
infof(data, "\n");
|
infof(data, "\n");
|
||||||
#endif /* CURL_LIBSSH2_DEBUG */
|
#endif /* CURL_LIBSSH2_DEBUG */
|
||||||
|
|
||||||
|
/* Before we authenticate we check the hostkey's MD5 fingerprint
|
||||||
|
* against a known fingerprint, if available. This implementation pulls
|
||||||
|
* it from the curl option.
|
||||||
|
*/
|
||||||
|
if (data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] &&
|
||||||
|
strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) == 32)
|
||||||
|
{
|
||||||
|
char buf[33];
|
||||||
|
host_public_key_md5 = libssh2_hostkey_hash(sftp_scp->ssh_session,
|
||||||
|
LIBSSH2_HOSTKEY_HASH_MD5);
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
snprintf(&buf[i*2], 3, "%02x",
|
||||||
|
(unsigned char) host_public_key_md5[i]);
|
||||||
|
if(!strequal(buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5])) {
|
||||||
|
failf(data,
|
||||||
|
"Denied establishing ssh session: mismatch md5 fingerprint. "
|
||||||
|
"Remote %s is not equal to %s",
|
||||||
|
buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]);
|
||||||
|
state(conn, SSH_SESSION_FREE);
|
||||||
|
sshc->actualCode = CURLE_FAILED_INIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
state(conn, SSH_AUTHLIST);
|
state(conn, SSH_AUTHLIST);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1836,7 +1836,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
|
result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
|
||||||
va_arg(param, char *));
|
va_arg(param, char *));
|
||||||
break;
|
break;
|
||||||
|
case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
|
||||||
|
/*
|
||||||
|
* Option to allow for the MD5 of the host public key to be checked
|
||||||
|
* for validation purposes.
|
||||||
|
*/
|
||||||
|
result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
|
||||||
|
va_arg(param, char *));
|
||||||
|
break;
|
||||||
case CURLOPT_HTTP_TRANSFER_DECODING:
|
case CURLOPT_HTTP_TRANSFER_DECODING:
|
||||||
/*
|
/*
|
||||||
* disable libcurl transfer encoding is used
|
* disable libcurl transfer encoding is used
|
||||||
|
@ -1289,6 +1289,7 @@ enum dupstring {
|
|||||||
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_USERPWD, /* <user:password>, if used */
|
STRING_USERPWD, /* <user:password>, if used */
|
||||||
|
STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
|
||||||
|
|
||||||
/* -- end of strings -- */
|
/* -- end of strings -- */
|
||||||
STRING_LAST /* not used, just an end-of-list marker */
|
STRING_LAST /* not used, just an end-of-list marker */
|
||||||
|
14
src/main.c
14
src/main.c
@ -407,6 +407,7 @@ struct Configurable {
|
|||||||
char *key_type;
|
char *key_type;
|
||||||
char *key_passwd;
|
char *key_passwd;
|
||||||
char *pubkey;
|
char *pubkey;
|
||||||
|
char *hostpubmd5;
|
||||||
char *engine;
|
char *engine;
|
||||||
bool list_engines;
|
bool list_engines;
|
||||||
bool crlf;
|
bool crlf;
|
||||||
@ -639,6 +640,7 @@ static void help(void)
|
|||||||
" --cacert <file> CA certificate to verify peer against (SSL)",
|
" --cacert <file> CA certificate to verify peer against (SSL)",
|
||||||
" --capath <directory> CA directory (made using c_rehash) to verify",
|
" --capath <directory> CA directory (made using c_rehash) to verify",
|
||||||
" peer against (SSL)",
|
" peer against (SSL)",
|
||||||
|
" --hostpubmd5 <md5> Hex encoded MD5 string of the host public key. (SSH)",
|
||||||
" --ciphers <list> SSL ciphers to use (SSL)",
|
" --ciphers <list> SSL ciphers to use (SSL)",
|
||||||
" --compressed Request compressed response (using deflate or gzip)",
|
" --compressed Request compressed response (using deflate or gzip)",
|
||||||
" --connect-timeout <seconds> Maximum time allowed for connection",
|
" --connect-timeout <seconds> Maximum time allowed for connection",
|
||||||
@ -1541,6 +1543,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
{"Ef","engine", TRUE},
|
{"Ef","engine", TRUE},
|
||||||
{"Eg","capath ", TRUE},
|
{"Eg","capath ", TRUE},
|
||||||
{"Eh","pubkey", TRUE},
|
{"Eh","pubkey", TRUE},
|
||||||
|
{"Ei", "hostpubmd5", TRUE},
|
||||||
{"f", "fail", FALSE},
|
{"f", "fail", FALSE},
|
||||||
{"F", "form", TRUE},
|
{"F", "form", TRUE},
|
||||||
{"Fs","form-string", TRUE},
|
{"Fs","form-string", TRUE},
|
||||||
@ -2159,6 +2162,11 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
case 'h': /* --pubkey public key file */
|
case 'h': /* --pubkey public key file */
|
||||||
GetStr(&config->pubkey, nextarg);
|
GetStr(&config->pubkey, nextarg);
|
||||||
break;
|
break;
|
||||||
|
case 'i': /* --hostpubmd5 md5 of the host public key */
|
||||||
|
GetStr(&config->hostpubmd5, nextarg);
|
||||||
|
if (!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
|
||||||
|
return PARAM_BAD_USE;
|
||||||
|
break;
|
||||||
default: /* certificate file */
|
default: /* certificate file */
|
||||||
{
|
{
|
||||||
char *ptr = strchr(nextarg, ':');
|
char *ptr = strchr(nextarg, ':');
|
||||||
@ -4206,6 +4214,12 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
my_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
|
my_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
|
||||||
my_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
|
my_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
|
||||||
|
|
||||||
|
/* SSH host key md5 checking allows us to fail if we are
|
||||||
|
* not talking to who we think we should
|
||||||
|
*/
|
||||||
|
my_setopt(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, config->hostpubmd5);
|
||||||
|
|
||||||
|
|
||||||
/* default to strict verifyhost */
|
/* default to strict verifyhost */
|
||||||
my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2);
|
my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2);
|
||||||
if(config->cacert || config->capath) {
|
if(config->cacert || config->capath) {
|
||||||
|
Loading…
Reference in New Issue
Block a user