SSH: move knownhost logic to separate function
authorDaniel Stenberg <daniel@haxx.se>
Wed, 20 Apr 2011 20:43:41 +0000 (22:43 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 27 Apr 2011 07:09:35 +0000 (09:09 +0200)
lib/ssh.c

index 81e3b3f..93b534b 100644 (file)
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -504,6 +504,129 @@ static int sshkeycallback(CURL *easy,
 #define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
 #endif
 
+static CURLcode ssh_knownhost(struct connectdata *conn)
+{
+  struct SessionHandle *data = conn->data;
+  CURLcode result = CURLE_OK;
+
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+  if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
+    /* we're asked to verify the host against a file */
+    struct ssh_conn *sshc = &conn->proto.sshc;
+    int rc;
+    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;
+    }
+  }
+#else /* HAVE_LIBSSH2_KNOWNHOST_API */
+  (void)conn;
+#endif
+  return result;
+}
+
+
 /*
  * ssh_statemach_act() runs the SSH state machine as far as it can without
  * blocking and without reaching the end.  The data the pointer 'block' points
@@ -595,118 +718,9 @@ 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);
+      result = ssh_knownhost(conn);
+      if(!result)
+        state(conn, SSH_AUTHLIST);
       break;
 
     case SSH_AUTHLIST: