diff --git a/subprojects/gst-plugins-bad/ext/curl/gstcurlsshsink.c b/subprojects/gst-plugins-bad/ext/curl/gstcurlsshsink.c index 7d5ef120a0..ec60db8ba6 100644 --- a/subprojects/gst-plugins-bad/ext/curl/gstcurlsshsink.c +++ b/subprojects/gst-plugins-bad/ext/curl/gstcurlsshsink.c @@ -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) */ diff --git a/subprojects/gst-plugins-bad/ext/curl/gstcurlsshsink.h b/subprojects/gst-plugins-bad/ext/curl/gstcurlsshsink.h index 376f1b1b28..a532a193a5 100644 --- a/subprojects/gst-plugins-bad/ext/curl/gstcurlsshsink.h +++ b/subprojects/gst-plugins-bad/ext/curl/gstcurlsshsink.h @@ -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 diff --git a/subprojects/gst-plugins-bad/tests/check/elements/curlsftpsink.c b/subprojects/gst-plugins-bad/tests/check/elements/curlsftpsink.c index 3dd265bd48..6d25adb661 100644 --- a/subprojects/gst-plugins-bad/tests/check/elements/curlsftpsink.c +++ b/subprojects/gst-plugins-bad/tests/check/elements/curlsftpsink.c @@ -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); }