curlsftpsink: Add support for sha256 fingerprint
authorMats Lindestam <matslm@axis.com>
Wed, 20 Oct 2021 11:19:00 +0000 (13:19 +0200)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 26 Oct 2021 12:18:40 +0000 (12:18 +0000)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1193>

subprojects/gst-plugins-bad/ext/curl/gstcurlsshsink.c
subprojects/gst-plugins-bad/ext/curl/gstcurlsshsink.h
subprojects/gst-plugins-bad/tests/check/elements/curlsftpsink.c

index 7d5ef12..ec60db8 100644 (file)
@@ -66,6 +66,7 @@ enum
   PROP_SSH_KEY_PASSPHRASE,
   PROP_SSH_KNOWNHOSTS,
   PROP_SSH_HOST_PUBLIC_KEY_MD5,
+  PROP_SSH_HOST_PUBLIC_KEY_SHA256,
   PROP_SSH_ACCEPT_UNKNOWNHOST
 };
 
@@ -167,6 +168,16 @@ gst_curl_ssh_sink_class_init (GstCurlSshSinkClass * klass)
           "remote host's public key",
           NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+#if CURL_AT_LEAST_VERSION(7, 80, 0)
+  g_object_class_install_property (gobject_class,
+      PROP_SSH_HOST_PUBLIC_KEY_SHA256,
+      g_param_spec_string ("ssh-host-pubkey-sha256",
+          "SHA256 checksum of the remote host's public key",
+          "SHA256 checksum (Base64 encoded) of the remote host's public key",
+          NULL, G_PARAM_READWRITE | GST_PARAM_CONDITIONALLY_AVAILABLE |
+          G_PARAM_STATIC_STRINGS));
+#endif
+
   g_object_class_install_property (gobject_class, PROP_SSH_ACCEPT_UNKNOWNHOST,
       g_param_spec_boolean ("ssh-accept-unknownhost",
           "SSH accept unknown host",
@@ -186,6 +197,7 @@ gst_curl_ssh_sink_init (GstCurlSshSink * sink)
   sink->ssh_key_passphrase = NULL;
   sink->ssh_knownhosts = NULL;
   sink->ssh_host_public_key_md5 = NULL;
+  sink->ssh_host_public_key_sha256 = NULL;
   sink->ssh_accept_unknownhost = FALSE;
 }
 
@@ -201,6 +213,7 @@ gst_curl_ssh_sink_finalize (GObject * gobject)
   g_free (this->ssh_key_passphrase);
   g_free (this->ssh_knownhosts);
   g_free (this->ssh_host_public_key_md5);
+  g_free (this->ssh_host_public_key_sha256);
 
   G_OBJECT_CLASS (parent_class)->finalize (gobject);
 }
@@ -262,6 +275,13 @@ gst_curl_ssh_sink_set_property (GObject * object, guint prop_id,
           sink->ssh_host_public_key_md5);
       break;
 
+    case PROP_SSH_HOST_PUBLIC_KEY_SHA256:
+      g_free (sink->ssh_host_public_key_sha256);
+      sink->ssh_host_public_key_sha256 = g_value_dup_string (value);
+      GST_DEBUG_OBJECT (sink, "ssh_host_public_key_sha256 set to %s",
+          sink->ssh_host_public_key_sha256);
+      break;
+
     case PROP_SSH_ACCEPT_UNKNOWNHOST:
       sink->ssh_accept_unknownhost = g_value_get_boolean (value);
       GST_DEBUG_OBJECT (sink, "ssh_accept_unknownhost set to %d",
@@ -309,6 +329,10 @@ gst_curl_ssh_sink_get_property (GObject * object, guint prop_id,
       g_value_set_string (value, sink->ssh_host_public_key_md5);
       break;
 
+    case PROP_SSH_HOST_PUBLIC_KEY_SHA256:
+      g_value_set_string (value, sink->ssh_host_public_key_sha256);
+      break;
+
     case PROP_SSH_ACCEPT_UNKNOWNHOST:
       g_value_set_boolean (value, sink->ssh_accept_unknownhost);
       break;
@@ -371,6 +395,17 @@ gst_curl_ssh_sink_set_options_unlocked (GstCurlBaseSink * bcsink)
       return FALSE;
     }
   }
+#if CURL_AT_LEAST_VERSION(7, 80, 0)
+  if (sink->ssh_host_public_key_sha256) {
+    if ((curl_err =
+            curl_easy_setopt (bcsink->curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
+                sink->ssh_host_public_key_sha256)) != CURLE_OK) {
+      bcsink->error = g_strdup_printf ("failed to set remote host's public "
+          "key SHA256: %s", curl_easy_strerror (curl_err));
+      return FALSE;
+    }
+  }
+#endif
 
   /* make sure we only accept PASSWORD or PUBLICKEY auth methods
    * (can be extended later) */
index 376f1b1..a532a19 100644 (file)
@@ -74,6 +74,9 @@ struct _GstCurlSshSink
                                            from remote host */
   gchar *ssh_host_public_key_md5;   /* MD5-hash of the remote host's public key:
                                        CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 */
+  gchar *ssh_host_public_key_sha256; /* SHA256-hash of the remote host's public
+                                        key: CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256
+                                      */
 };
 
 struct _GstCurlSshSinkClass
index 3dd265b..6d25adb 100644 (file)
@@ -52,6 +52,7 @@ GST_START_TEST (test_properties)
   gchar *res_passphrase = NULL;
   gchar *res_kh_file = NULL;
   gchar *res_host_pubkey_md5 = NULL;
+  gchar *res_host_pubkey_sha256 = NULL;
   guint res_auth_type = 0;
   gboolean res_accept_unkh = FALSE;
 
@@ -76,6 +77,10 @@ GST_START_TEST (test_properties)
   g_object_set (G_OBJECT (sink), "ssh-knownhosts", "known_hosts", NULL);
   g_object_set (G_OBJECT (sink), "ssh-host-pubkey-md5",
       "00112233445566778899aabbccddeeff", NULL);
+#if CURL_AT_LEAST_VERSION(7, 80, 0)
+  g_object_set (G_OBJECT (sink), "ssh-host-pubkey-sha256",
+      "TQtiu1/zwGEEKG4z/PDfPE/ak47AF9nbWHykx4CWcu9", NULL);
+#endif
   g_object_set (G_OBJECT (sink), "ssh-accept-unknownhost", TRUE, NULL);
   g_object_set (G_OBJECT (sink), "ssh-key-passphrase", "SoMePaSsPhRaSe", NULL);
 
@@ -94,6 +99,10 @@ GST_START_TEST (test_properties)
       "create-dirs", &res_create_dirs, "ssh-key-passphrase", &res_passphrase,
       NULL);
 
+#if CURL_AT_LEAST_VERSION(7, 80, 0)
+  g_object_get (sink, "ssh-host-pubkey-sha256", &res_host_pubkey_sha256, NULL);
+#endif
+
   fail_unless (strncmp (res_location, "test_location", strlen ("test_location"))
       == 0);
   fail_unless (strncmp (res_user, "test_user", strlen ("test_user")) == 0);
@@ -113,6 +122,11 @@ GST_START_TEST (test_properties)
       == 0);
   fail_unless (strncmp (res_host_pubkey_md5, "00112233445566778899aabbccddeeff",
           strlen ("00112233445566778899aabbccddeeff")) == 0);
+#if CURL_AT_LEAST_VERSION(7, 80, 0)
+  fail_unless (strncmp (res_host_pubkey_sha256,
+          "TQtiu1/zwGEEKG4z/PDfPE/ak47AF9nbWHykx4CWcu9",
+          strlen ("TQtiu1/zwGEEKG4z/PDfPE/ak47AF9nbWHykx4CWcu9")) == 0);
+#endif
   fail_unless (strncmp (res_passphrase, "SoMePaSsPhRaSe",
           strlen ("SoMePaSsPhRaSe")) == 0);
   fail_unless (res_accept_unkh == TRUE);
@@ -127,6 +141,7 @@ GST_START_TEST (test_properties)
   g_free (res_passphrase);
   g_free (res_kh_file);
   g_free (res_host_pubkey_md5);
+  g_free (res_host_pubkey_sha256);
 
   /* ------- change properties ------------- */
 
@@ -145,6 +160,10 @@ GST_START_TEST (test_properties)
   g_object_set (G_OBJECT (sink), "ssh-knownhosts", "/zzz/known_hosts", NULL);
   g_object_set (G_OBJECT (sink), "ssh-host-pubkey-md5",
       "ffeeddccbbaa99887766554433221100", NULL);
+#if CURL_AT_LEAST_VERSION(7, 80, 0)
+  g_object_set (G_OBJECT (sink), "ssh-host-pubkey-sha256",
+      "TUtitut/wGEEKG4z/PDfPE/ak47AF7nbWHykAxCWcu5", NULL);
+#endif
   g_object_set (G_OBJECT (sink), "ssh-accept-unknownhost", FALSE, NULL);
   g_object_set (G_OBJECT (sink), "ssh-key-passphrase", "OtherPASSphrase", NULL);
 
@@ -163,6 +182,10 @@ GST_START_TEST (test_properties)
       "ssh-key-passphrase", &res_passphrase, "create-dirs", &res_create_dirs,
       NULL);
 
+#if CURL_AT_LEAST_VERSION(7, 80, 0)
+  g_object_get (sink, "ssh-host-pubkey-sha256", &res_host_pubkey_sha256, NULL);
+#endif
+
   fail_unless (strncmp (res_location, "new_location", strlen ("new_location"))
       == 0);
   fail_unless (strncmp (res_user, "new_user", strlen ("new_user")) == 0);
@@ -182,6 +205,11 @@ GST_START_TEST (test_properties)
           strlen ("/zzz/known_host")) == 0);
   fail_unless (strncmp (res_host_pubkey_md5, "ffeeddccbbaa99887766554433221100",
           strlen ("ffeeddccbbaa99887766554433221100")) == 0);
+#if CURL_AT_LEAST_VERSION(7, 80, 0)
+  fail_unless (strncmp (res_host_pubkey_sha256,
+          "TUtitut/wGEEKG4z/PDfPE/ak47AF7nbWHykAxCWcu5",
+          strlen ("TUtitut/wGEEKG4z/PDfPE/ak47AF7nbWHykAxCWcu5")) == 0);
+#endif
   fail_unless (strncmp (res_passphrase, "OtherPASSphrase",
           strlen ("OtherPASSphrase")) == 0);
   fail_unless (res_accept_unkh == FALSE);
@@ -196,6 +224,7 @@ GST_START_TEST (test_properties)
   g_free (res_passphrase);
   g_free (res_kh_file);
   g_free (res_host_pubkey_md5);
+  g_free (res_host_pubkey_256);
 
   cleanup_curlsftpsink (sink);
 }