aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2007-10-03 08:00:42 +0000
committerDaniel Stenberg <daniel@haxx.se>2007-10-03 08:00:42 +0000
commit51c6a5d43b09835289a469165aa7a2bfb79dbdc6 (patch)
tree49b4c738d465d09c72fd048bb77b91514058b40c /lib
parent15b8da1980538f5c56115777610867230b0ac9d1 (diff)
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/ssh.c27
-rw-r--r--lib/url.c9
-rw-r--r--lib/urldata.h1
3 files changed, 35 insertions, 2 deletions
diff --git a/lib/ssh.c b/lib/ssh.c
index d56eb855c..4a9d03732 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -310,7 +310,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
#ifdef CURL_LIBSSH2_DEBUG
const char *fingerprint;
#endif /* CURL_LIBSSH2_DEBUG */
- int rc;
+ const char *host_public_key_md5;
+ int rc,i;
long err;
switch(sshc->state) {
@@ -351,6 +352,30 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
infof(data, "\n");
#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);
break;
diff --git a/lib/url.c b/lib/url.c
index afb0b3837..c91d062fe 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1836,7 +1836,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
va_arg(param, char *));
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:
/*
* disable libcurl transfer encoding is used
diff --git a/lib/urldata.h b/lib/urldata.h
index 4ed161a5f..72bd0eb83 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1289,6 +1289,7 @@ enum dupstring {
STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
STRING_USERAGENT, /* User-Agent string */
STRING_USERPWD, /* <user:password>, if used */
+ STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
/* -- end of strings -- */
STRING_LAST /* not used, just an end-of-list marker */