mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 11:45:25 +00:00
curlsftpsink: authenticate remote host via public key fingerprint
Expose one more libcurl option: CURLOPT_SSH_HOST_PUBLIC_KEY_MD5. This allows authenticating the server by the MD5 fingerprint of the server's public key. https://bugzilla.gnome.org/show_bug.cgi?id=723167
This commit is contained in:
parent
0cdcc5a7b1
commit
9c1e66302d
3 changed files with 56 additions and 2 deletions
|
@ -48,8 +48,6 @@
|
|||
|
||||
/* Default values */
|
||||
#define GST_CAT_DEFAULT gst_curl_ssh_sink_debug
|
||||
#define DEFAULT_INSECURE TRUE
|
||||
|
||||
|
||||
/* Plugin specific settings */
|
||||
|
||||
|
@ -63,6 +61,7 @@ enum
|
|||
PROP_SSH_PRIV_KEYFILE,
|
||||
PROP_SSH_KEY_PASSPHRASE,
|
||||
PROP_SSH_KNOWNHOSTS,
|
||||
PROP_SSH_HOST_PUBLIC_KEY_MD5,
|
||||
PROP_SSH_ACCEPT_UNKNOWNHOST
|
||||
};
|
||||
|
||||
|
@ -159,6 +158,13 @@ gst_curl_ssh_sink_class_init (GstCurlSshSinkClass * klass)
|
|||
"The complete path & filename of the SSH 'known_hosts' file",
|
||||
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_SSH_HOST_PUBLIC_KEY_MD5,
|
||||
g_param_spec_string ("ssh-host-pubkey-md5",
|
||||
"MD5 checksum of the remote host's public key",
|
||||
"MD5 checksum (32 hexadecimal digits, case-insensitive) of the "
|
||||
"remote host's public key",
|
||||
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_SSH_ACCEPT_UNKNOWNHOST,
|
||||
g_param_spec_boolean ("ssh-accept-unknownhost",
|
||||
"SSH accept unknown host",
|
||||
|
@ -174,6 +180,7 @@ gst_curl_ssh_sink_init (GstCurlSshSink * sink)
|
|||
sink->ssh_priv_keyfile = NULL;
|
||||
sink->ssh_key_passphrase = NULL;
|
||||
sink->ssh_knownhosts = NULL;
|
||||
sink->ssh_host_public_key_md5 = NULL;
|
||||
sink->ssh_accept_unknownhost = FALSE;
|
||||
}
|
||||
|
||||
|
@ -188,6 +195,7 @@ gst_curl_ssh_sink_finalize (GObject * gobject)
|
|||
g_free (this->ssh_priv_keyfile);
|
||||
g_free (this->ssh_key_passphrase);
|
||||
g_free (this->ssh_knownhosts);
|
||||
g_free (this->ssh_host_public_key_md5);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (gobject);
|
||||
}
|
||||
|
@ -242,6 +250,13 @@ gst_curl_ssh_sink_set_property (GObject * object, guint prop_id,
|
|||
GST_DEBUG_OBJECT (sink, "ssh_knownhosts set to %s", sink->ssh_knownhosts);
|
||||
break;
|
||||
|
||||
case PROP_SSH_HOST_PUBLIC_KEY_MD5:
|
||||
g_free (sink->ssh_host_public_key_md5);
|
||||
sink->ssh_host_public_key_md5 = g_value_dup_string (value);
|
||||
GST_DEBUG_OBJECT (sink, "ssh_host_public_key_md5 set to %s",
|
||||
sink->ssh_host_public_key_md5);
|
||||
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",
|
||||
|
@ -285,6 +300,10 @@ gst_curl_ssh_sink_get_property (GObject * object, guint prop_id,
|
|||
g_value_set_string (value, sink->ssh_knownhosts);
|
||||
break;
|
||||
|
||||
case PROP_SSH_HOST_PUBLIC_KEY_MD5:
|
||||
g_value_set_string (value, sink->ssh_host_public_key_md5);
|
||||
break;
|
||||
|
||||
case PROP_SSH_ACCEPT_UNKNOWNHOST:
|
||||
g_value_set_boolean (value, sink->ssh_accept_unknownhost);
|
||||
break;
|
||||
|
@ -329,6 +348,26 @@ gst_curl_ssh_sink_set_options_unlocked (GstCurlBaseSink * bcsink)
|
|||
}
|
||||
}
|
||||
|
||||
if (sink->ssh_host_public_key_md5) {
|
||||
/* libcurl is freaking tricky. If the input string is not exactly 32
|
||||
* hexdigits long it silently ignores CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 and
|
||||
* performs the transfer without authenticating the server! */
|
||||
if (strlen (sink->ssh_host_public_key_md5) != 32) {
|
||||
GST_ERROR_OBJECT (sink,
|
||||
"MD5-hash string has invalid length, must be exactly 32 hexdigits!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((curl_err =
|
||||
curl_easy_setopt (bcsink->curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
|
||||
sink->ssh_host_public_key_md5)) != CURLE_OK) {
|
||||
GST_ERROR_OBJECT (sink,
|
||||
"curl error: %d setting remote host's public key MD5: %s.", curl_err,
|
||||
sink->ssh_host_public_key_md5);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* make sure we only accept PASSWORD or PUBLICKEY auth methods
|
||||
* (can be extended later) */
|
||||
if (sink->ssh_auth_type == CURLSSH_AUTH_PASSWORD ||
|
||||
|
|
|
@ -70,6 +70,8 @@ struct _GstCurlSshSink
|
|||
CURLOPT_SSH_KNOWN_HOSTS */
|
||||
gboolean ssh_accept_unknownhost; /* accept or reject unknown public key
|
||||
from remote host */
|
||||
gchar *ssh_host_public_key_md5; /* MD5-hash of the remote host's public key:
|
||||
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 */
|
||||
};
|
||||
|
||||
struct _GstCurlSshSinkClass
|
||||
|
|
|
@ -51,6 +51,7 @@ GST_START_TEST (test_properties)
|
|||
gchar *res_privkey_file = NULL;
|
||||
gchar *res_passphrase = NULL;
|
||||
gchar *res_kh_file = NULL;
|
||||
gchar *res_host_pubkey_md5 = NULL;
|
||||
guint res_auth_type = 0;
|
||||
gboolean res_accept_unkh = FALSE;
|
||||
|
||||
|
@ -73,6 +74,8 @@ GST_START_TEST (test_properties)
|
|||
g_object_set (G_OBJECT (sink), "ssh-pub-keyfile", "public_key_file", NULL);
|
||||
g_object_set (G_OBJECT (sink), "ssh-priv-keyfile", "private_key_file", NULL);
|
||||
g_object_set (G_OBJECT (sink), "ssh-knownhosts", "known_hosts", NULL);
|
||||
g_object_set (G_OBJECT (sink), "ssh-host-pubkey-md5",
|
||||
"00112233445566778899aabbccddeeff", NULL);
|
||||
g_object_set (G_OBJECT (sink), "ssh-accept-unknownhost", TRUE, NULL);
|
||||
g_object_set (G_OBJECT (sink), "ssh-key-passphrase", "SoMePaSsPhRaSe", NULL);
|
||||
|
||||
|
@ -86,6 +89,7 @@ GST_START_TEST (test_properties)
|
|||
"timeout", &res_timeout, "qos-dscp", &res_qos_dscp,
|
||||
"ssh-auth-type", &res_auth_type, "ssh-pub-keyfile", &res_pubkey_file,
|
||||
"ssh-priv-keyfile", &res_privkey_file, "ssh-knownhosts", &res_kh_file,
|
||||
"ssh-host-pubkey-md5", &res_host_pubkey_md5,
|
||||
"ssh-accept-unknownhost", &res_accept_unkh,
|
||||
"create-dirs", &res_create_dirs, "ssh-key-passphrase", &res_passphrase,
|
||||
NULL);
|
||||
|
@ -107,6 +111,8 @@ GST_START_TEST (test_properties)
|
|||
strlen ("private_key_file")) == 0);
|
||||
fail_unless (strncmp (res_kh_file, "known_hosts", strlen ("known_hosts"))
|
||||
== 0);
|
||||
fail_unless (strncmp (res_host_pubkey_md5, "00112233445566778899aabbccddeeff",
|
||||
strlen ("00112233445566778899aabbccddeeff")) == 0);
|
||||
fail_unless (strncmp (res_passphrase, "SoMePaSsPhRaSe",
|
||||
strlen ("SoMePaSsPhRaSe")) == 0);
|
||||
fail_unless (res_accept_unkh == TRUE);
|
||||
|
@ -120,6 +126,7 @@ GST_START_TEST (test_properties)
|
|||
g_free (res_privkey_file);
|
||||
g_free (res_passphrase);
|
||||
g_free (res_kh_file);
|
||||
g_free (res_host_pubkey_md5);
|
||||
|
||||
/* ------- change properties ------------- */
|
||||
|
||||
|
@ -136,6 +143,8 @@ GST_START_TEST (test_properties)
|
|||
g_object_set (G_OBJECT (sink), "ssh-pub-keyfile", "/xxx/pub_key", NULL);
|
||||
g_object_set (G_OBJECT (sink), "ssh-priv-keyfile", "/yyy/pvt_key", NULL);
|
||||
g_object_set (G_OBJECT (sink), "ssh-knownhosts", "/zzz/known_hosts", NULL);
|
||||
g_object_set (G_OBJECT (sink), "ssh-host-pubkey-md5",
|
||||
"ffeeddccbbaa99887766554433221100", NULL);
|
||||
g_object_set (G_OBJECT (sink), "ssh-accept-unknownhost", FALSE, NULL);
|
||||
g_object_set (G_OBJECT (sink), "ssh-key-passphrase", "OtherPASSphrase", NULL);
|
||||
|
||||
|
@ -150,6 +159,7 @@ GST_START_TEST (test_properties)
|
|||
"ssh-auth-type", &res_auth_type, "ssh-pub-keyfile", &res_pubkey_file,
|
||||
"ssh-priv-keyfile", &res_privkey_file, "ssh-knownhosts", &res_kh_file,
|
||||
"ssh-accept-unknownhost", &res_accept_unkh,
|
||||
"ssh-host-pubkey-md5", &res_host_pubkey_md5,
|
||||
"ssh-key-passphrase", &res_passphrase, "create-dirs", &res_create_dirs,
|
||||
NULL);
|
||||
|
||||
|
@ -170,6 +180,8 @@ GST_START_TEST (test_properties)
|
|||
strlen ("/yyy/pvt_key")) == 0);
|
||||
fail_unless (strncmp (res_kh_file, "/zzz/known_hosts",
|
||||
strlen ("/zzz/known_host")) == 0);
|
||||
fail_unless (strncmp (res_host_pubkey_md5, "ffeeddccbbaa99887766554433221100",
|
||||
strlen ("ffeeddccbbaa99887766554433221100")) == 0);
|
||||
fail_unless (strncmp (res_passphrase, "OtherPASSphrase",
|
||||
strlen ("OtherPASSphrase")) == 0);
|
||||
fail_unless (res_accept_unkh == FALSE);
|
||||
|
@ -183,6 +195,7 @@ GST_START_TEST (test_properties)
|
|||
g_free (res_privkey_file);
|
||||
g_free (res_passphrase);
|
||||
g_free (res_kh_file);
|
||||
g_free (res_host_pubkey_md5);
|
||||
|
||||
cleanup_curlsftpsink (sink);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue