From 8989360664f68944ca6c00e69b2d88194fed4c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Mon, 5 May 2014 20:29:44 -0400 Subject: rtpsession: Factor out SRTP parameter validation --- gst/fsrtpconference/fs-rtp-session.c | 173 ++-------------------------------- gst/fsrtpconference/fs-rtp-stream.c | 177 +++++++++++++++++++++++++++++++++++ gst/fsrtpconference/fs-rtp-stream.h | 5 + 3 files changed, 192 insertions(+), 163 deletions(-) (limited to 'gst') diff --git a/gst/fsrtpconference/fs-rtp-session.c b/gst/fsrtpconference/fs-rtp-session.c index d82c4f2f..662420ec 100644 --- a/gst/fsrtpconference/fs-rtp-session.c +++ b/gst/fsrtpconference/fs-rtp-session.c @@ -5351,90 +5351,27 @@ invalid: return TRUE; } -static gint -parse_enum (const gchar *name, const gchar *value, GError **error) -{ - GstElementFactory *factory; - GstPluginFeature *loaded_feature; - GType srtpenc_type; - GObjectClass *srtpenc_class; - GParamSpec *spec; - GParamSpecEnum *enumspec; - GEnumValue *enumvalue; - - if (value == NULL) - goto error; - - factory = gst_element_factory_find ("srtpenc"); - if (!factory) - goto error_not_installed; - - loaded_feature = gst_plugin_feature_load (GST_PLUGIN_FEATURE (factory)); - gst_object_unref (factory); - factory = GST_ELEMENT_FACTORY (loaded_feature); - - srtpenc_type = gst_element_factory_get_element_type (factory); - gst_object_unref (factory); - if (srtpenc_type == 0) - goto error_not_installed; - - srtpenc_class = g_type_class_ref (srtpenc_type); - if (!srtpenc_class) - goto error_not_installed; - - spec = g_object_class_find_property (srtpenc_class, name); - g_type_class_unref (srtpenc_class); - if (!spec) - goto error_internal; - - if (!G_IS_PARAM_SPEC_ENUM (spec)) - goto error_internal; - enumspec = G_PARAM_SPEC_ENUM (spec); - - enumvalue = g_enum_get_value_by_nick (enumspec->enum_class, value); - if (enumvalue) - return enumvalue->value; - - enumvalue = g_enum_get_value_by_name (enumspec->enum_class, value); - if (enumvalue) - return enumvalue->value; - -error: - g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, - "Invalid %s value: %s", name, value); - return -1; - -error_not_installed: - g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, - "Can't find srtpenc, no encryption possible"); - return -1; - -error_internal: - g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL, - "Can't find srtpenc %s property or is not a GEnum type!", name); - return -1; -} - static gboolean fs_rtp_session_set_encryption_parameters (FsSession *session, GstStructure *parameters, GError **error) { FsRtpSession *self = FS_RTP_SESSION (session); gboolean ret = FALSE; - const gchar *tmp; - GstBuffer *key = NULL; - gint cipher = 0; /* 0 is null cipher, no encryption */ - gint rtp_cipher = -1; - gint rtcp_cipher = -1; - gint auth = -1; - gint rtp_auth = -1; - gint rtcp_auth = -1; - guint replay_window_size = 0; + GstBuffer *key; + gint rtp_cipher; + gint rtcp_cipher; + gint rtp_auth; + gint rtcp_auth; + guint replay_window_size; g_return_val_if_fail (FS_IS_RTP_SESSION (session), FALSE); g_return_val_if_fail (parameters == NULL || GST_IS_STRUCTURE (parameters), FALSE); + if (!validate_srtp_parameters (parameters, &rtp_cipher, &rtcp_cipher, + &rtp_auth, &rtcp_auth, &key, &replay_window_size, error)) + return FALSE; + if (fs_rtp_session_has_disposed_enter (self, error)) return FALSE; @@ -5445,96 +5382,6 @@ fs_rtp_session_set_encryption_parameters (FsSession *session, goto done; } - if (parameters) { - const GValue *v = NULL; - - if (!gst_structure_has_name (parameters, "FarstreamSRTPEncrypt")) - { - g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, - "The only structure accepted is FarstreamSRTPEncrypt"); - goto done; - } - if ((tmp = gst_structure_get_string (parameters, "cipher"))) - { - cipher = parse_enum ("rtp-cipher", tmp, error); - if (cipher == -1) - goto done; - } - if ((tmp = gst_structure_get_string (parameters, "rtp-cipher"))) - { - rtp_cipher = parse_enum ("rtp-cipher", tmp, error); - if (cipher == -1) - goto done; - } - if ((tmp = gst_structure_get_string (parameters, "rtcp-cipher"))) - { - rtcp_cipher = parse_enum ("rtcp-cipher", tmp, error); - if (cipher == -1) - goto done; - } - if ((tmp = gst_structure_get_string (parameters, "auth"))) - { - auth = parse_enum ("rtp-auth", tmp, error); - if (cipher == -1) - goto done; - } - if ((tmp = gst_structure_get_string (parameters, "rtp-auth"))) - { - rtp_auth = parse_enum ("rtp-auth", tmp, error); - if (cipher == -1) - goto done; - } - if ((tmp = gst_structure_get_string (parameters, "rtcp-auth"))) - { - rtcp_auth = parse_enum ("rtcp-auth", tmp, error); - if (cipher == -1) - goto done; - } - - if (rtp_cipher == -1) - rtp_cipher = cipher; - if (rtcp_cipher == -1) - rtcp_cipher = cipher; - - if (rtp_auth == -1) - rtp_auth = auth; - if (rtcp_auth == -1) - rtcp_auth = auth; - if (rtp_auth == -1 || rtcp_auth == -1) - { - g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, - "At least the authentication MUST be set, \"auth\" or \"rtp-auth\"" - " and \"rtcp-auth\" are required."); - goto done; - } - - v = gst_structure_get_value (parameters, "key"); - if (!v) { - g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, - "The argument \"key\" is required."); - goto done; - } - if (!GST_VALUE_HOLDS_BUFFER (v) || gst_value_get_buffer (v) == NULL) { - g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, - "The argument \"key\" MUST hold a GstBuffer."); - goto done; - } - key = gst_value_get_buffer (v); - - if (gst_structure_get_uint (parameters, "replay-window-size", - &replay_window_size)) - { - if (replay_window_size < 64 || replay_window_size >= 32768) { - g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, - "Reply window size must be between 64 and 32768"); - goto done; - } - } - } else { - rtcp_auth = rtp_auth = 0; /* 0 is NULL */ - } - - FS_RTP_SESSION_LOCK (self); if (self->priv->encryption_parameters) gst_structure_free (self->priv->encryption_parameters); diff --git a/gst/fsrtpconference/fs-rtp-stream.c b/gst/fsrtpconference/fs-rtp-stream.c index 12744596..9b242c81 100644 --- a/gst/fsrtpconference/fs-rtp-stream.c +++ b/gst/fsrtpconference/fs-rtp-stream.c @@ -1157,3 +1157,180 @@ fs_rtp_stream_set_transmitter (FsStream *stream, g_object_unref (session); return TRUE; } + +static gint +parse_enum (const gchar *name, const gchar *value, GError **error) +{ + GstElementFactory *factory; + GstPluginFeature *loaded_feature; + GType srtpenc_type; + GObjectClass *srtpenc_class; + GParamSpec *spec; + GParamSpecEnum *enumspec; + GEnumValue *enumvalue; + + if (value == NULL) + goto error; + + factory = gst_element_factory_find ("srtpenc"); + if (!factory) + goto error_not_installed; + + loaded_feature = gst_plugin_feature_load (GST_PLUGIN_FEATURE (factory)); + gst_object_unref (factory); + factory = GST_ELEMENT_FACTORY (loaded_feature); + + srtpenc_type = gst_element_factory_get_element_type (factory); + gst_object_unref (factory); + if (srtpenc_type == 0) + goto error_not_installed; + + srtpenc_class = g_type_class_ref (srtpenc_type); + if (!srtpenc_class) + goto error_not_installed; + + spec = g_object_class_find_property (srtpenc_class, name); + g_type_class_unref (srtpenc_class); + if (!spec) + goto error_internal; + + if (!G_IS_PARAM_SPEC_ENUM (spec)) + goto error_internal; + enumspec = G_PARAM_SPEC_ENUM (spec); + + enumvalue = g_enum_get_value_by_nick (enumspec->enum_class, value); + if (enumvalue) + return enumvalue->value; + + enumvalue = g_enum_get_value_by_name (enumspec->enum_class, value); + if (enumvalue) + return enumvalue->value; + +error: + g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, + "Invalid %s value: %s", name, value); + return -1; + +error_not_installed: + g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, + "Can't find srtpenc, no encryption possible"); + return -1; + +error_internal: + g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL, + "Can't find srtpenc %s property or is not a GEnum type!", name); + return -1; +} + + +gboolean +validate_srtp_parameters (GstStructure *parameters, + gint *srtp_cipher, gint *srtcp_cipher, gint *srtp_auth, gint *srtcp_auth, + GstBuffer **key, guint *replay_window, GError **error) +{ + gint cipher = 0; /* 0 is null cipher, no encryption */ + gint auth = -1; + + *key = NULL; + *srtp_cipher = -1; + *srtcp_cipher = -1; + *srtp_auth = -1; + *srtcp_auth = -1; + *replay_window = 128; + + if (parameters) + { + const GValue *v = NULL; + const gchar *tmp; + + if (!gst_structure_has_name (parameters, "FarstreamSRTP")) + { + g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, + "The only structure accepted is FarstreamSRTP"); + return FALSE; + } + if ((tmp = gst_structure_get_string (parameters, "cipher"))) + { + cipher = parse_enum ("rtp-cipher", tmp, error); + if (cipher == -1) + return FALSE; + } + if ((tmp = gst_structure_get_string (parameters, "rtp-cipher"))) + { + *srtp_cipher = parse_enum ("rtp-cipher", tmp, error); + if (cipher == -1) + return FALSE; + } + if ((tmp = gst_structure_get_string (parameters, "rtcp-cipher"))) + { + *srtcp_cipher = parse_enum ("rtcp-cipher", tmp, error); + if (cipher == -1) + return FALSE; + } + if ((tmp = gst_structure_get_string (parameters, "auth"))) + { + auth = parse_enum ("rtp-auth", tmp, error); + if (cipher == -1) + return FALSE; + } + if ((tmp = gst_structure_get_string (parameters, "rtp-auth"))) + { + *srtp_auth = parse_enum ("rtp-auth", tmp, error); + if (cipher == -1) + return FALSE; + } + if ((tmp = gst_structure_get_string (parameters, "rtcp-auth"))) + { + *srtcp_auth = parse_enum ("rtcp-auth", tmp, error); + if (cipher == -1) + return FALSE; + } + + if (*srtp_cipher == -1) + *srtp_cipher = cipher; + if (*srtcp_cipher == -1) + *srtcp_cipher = cipher; + + if (*srtp_auth == -1) + *srtp_auth = auth; + if (*srtcp_auth == -1) + *srtcp_auth = auth; + if (*srtp_auth == -1 || *srtcp_auth == -1) + { + g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, + "At least the authentication MUST be set, \"auth\" or \"rtp-auth\"" + " and \"rtcp-auth\" are required."); + return FALSE; + } + + v = gst_structure_get_value (parameters, "key"); + if (!v) + { + g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, + "The argument \"key\" is required."); + return FALSE; + } + if (!GST_VALUE_HOLDS_BUFFER (v) || gst_value_get_buffer (v) == NULL) + { + g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, + "The argument \"key\" MUST hold a GstBuffer."); + return FALSE; + } + *key = gst_value_get_buffer (v); + + if (gst_structure_get_uint (parameters, "replay-window-size", + replay_window)) + { + if (*replay_window < 64 || *replay_window >= 32768) + { + g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS, + "Reply window size must be between 64 and 32768"); + return FALSE; + } + } + } else { + *srtp_cipher = *srtcp_cipher = *srtcp_auth = *srtp_auth = 0; /* 0 is NULL */ + } + + return TRUE; +} diff --git a/gst/fsrtpconference/fs-rtp-stream.h b/gst/fsrtpconference/fs-rtp-stream.h index 9f1878b6..5fa1c7b8 100644 --- a/gst/fsrtpconference/fs-rtp-stream.h +++ b/gst/fsrtpconference/fs-rtp-stream.h @@ -121,6 +121,11 @@ void fs_rtp_stream_set_negotiated_codecs_unlock (FsRtpStream *stream, GList *codecs); +gboolean +validate_srtp_parameters (GstStructure *parameters, + gint *srtp_cipher, gint *srtcp_cipher, gint *srtp_auth, gint *srtcp_auth, + GstBuffer **key, guint *replay_window, GError **error); + G_END_DECLS #endif /* __FS_RTP_STREAM_H__ */ -- cgit v1.2.1