Index: include/curl/curl.h
===================================================================
RCS file: /cvsroot/curl/curl/include/curl/curl.h,v
retrieving revision 1.325
diff -u -b -B -r1.325 curl.h
--- include/curl/curl.h	26 Sep 2007 12:44:59 -0000	1.325
+++ include/curl/curl.h	2 Oct 2007 10:57:31 -0000
@@ -1127,6 +1127,9 @@
   /* Obey RFC 2616/10.3.2 and keep POSTs as POSTs after a 301 */
   CINIT(POST301, LONG, 161),
 
+  /* used by scp/sftp to verify the host public key */
+  CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
Index: lib/ssh.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/ssh.c,v
retrieving revision 1.75
diff -u -b -B -r1.75 ssh.c
--- lib/ssh.c	29 Sep 2007 21:34:34 -0000	1.75
+++ lib/ssh.c	2 Oct 2007 10:57:32 -0000
@@ -310,7 +310,8 @@
 #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,28 @@
       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], 2, "%02x",
+                   (unsigned char) host_public_key_md5[i]);
+        if(!strequal(buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5])) {
+          failf(data,
+                "Failure establishing ssh session: mismatch md5 fingerprint");
+          state(conn, SSH_SESSION_FREE);
+          sshc->actualCode = CURLE_FAILED_INIT;
+          break;
+        }
+      }
+
       state(conn, SSH_AUTHLIST);
       break;
 
Index: lib/url.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/url.c,v
retrieving revision 1.647
diff -u -b -B -r1.647 url.c
--- lib/url.c	27 Sep 2007 01:45:23 -0000	1.647
+++ lib/url.c	2 Oct 2007 10:57:34 -0000
@@ -1836,7 +1836,14 @@
     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
Index: lib/urldata.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/urldata.h,v
retrieving revision 1.347
diff -u -b -B -r1.347 urldata.h
--- lib/urldata.h	2 Oct 2007 10:21:36 -0000	1.347
+++ lib/urldata.h	2 Oct 2007 10:57:34 -0000
@@ -1289,6 +1289,7 @@
   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 */
Index: src/main.c
===================================================================
RCS file: /cvsroot/curl/curl/src/main.c,v
retrieving revision 1.428
diff -u -b -B -r1.428 main.c
--- src/main.c	26 Sep 2007 12:44:59 -0000	1.428
+++ src/main.c	2 Oct 2007 10:57:35 -0000
@@ -407,6 +407,7 @@
   char *key_type;
   char *key_passwd;
   char *pubkey;
+  char *hostpubmd5;
   char *engine;
   bool list_engines;
   bool crlf;
@@ -639,6 +640,7 @@
     "    --cacert <file> CA certificate to verify peer against (SSL)",
     "    --capath <directory> CA directory (made using c_rehash) to verify",
     "                    peer against (SSL)",
+    "    --hostpubmd5 <md5> Hex encoded MD5 string of the host public key. (SSH)",
     "    --ciphers <list> SSL ciphers to use (SSL)",
     "    --compressed    Request compressed response (using deflate or gzip)",
     "    --connect-timeout <seconds> Maximum time allowed for connection",
@@ -1541,6 +1543,7 @@
     {"Ef","engine",      TRUE},
     {"Eg","capath ",     TRUE},
     {"Eh","pubkey",      TRUE},
+    {"Ei", "hostpubmd5", TRUE},
     {"f", "fail",        FALSE},
     {"F", "form",        TRUE},
     {"Fs","form-string", TRUE},
@@ -2159,6 +2162,11 @@
       case 'h': /* --pubkey public key file */
         GetStr(&config->pubkey, nextarg);
         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 */
         {
           char *ptr = strchr(nextarg, ':');
@@ -4206,6 +4214,12 @@
         my_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
         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 */
         my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2);
         if(config->cacert || config->capath) {
