neonhttp: add property to support SS cerificates
authorMathias Hasselmann <mathias.hasselmann at gmx.de>
Mon, 25 May 2009 15:24:32 +0000 (17:24 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Mon, 25 May 2009 15:24:32 +0000 (17:24 +0200)
Add a property to support self-signed certificates in neonhttpsrc. This property
is FALSE by default.
Fixes #511097

ext/neon/gstneonhttpsrc.c
ext/neon/gstneonhttpsrc.h

index 739b013..1af733d 100644 (file)
@@ -63,6 +63,7 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
 #define DEFAULT_IRADIO_GENRE         NULL
 #define DEFAULT_IRADIO_URL           NULL
 #define DEFAULT_AUTOMATIC_REDIRECT   TRUE
+#define DEFAULT_ACCEPT_SELF_SIGNED   FALSE
 #define DEFAULT_NEON_HTTP_DEBUG      FALSE
 
 enum
@@ -76,6 +77,7 @@ enum
   PROP_IRADIO_GENRE,
   PROP_IRADIO_URL,
   PROP_AUTOMATIC_REDIRECT,
+  PROP_ACCEPT_SELF_SIGNED,
 #ifndef GST_DISABLE_GST_DEBUG
   PROP_NEON_HTTP_DEBUG
 #endif
@@ -200,6 +202,12 @@ gst_neonhttp_src_class_init (GstNeonhttpSrcClass * klass)
           "Automatically follow HTTP redirects (HTTP Status Code 302/303)",
           TRUE, G_PARAM_READWRITE));
 
+  g_object_class_install_property
+      (gobject_class, PROP_ACCEPT_SELF_SIGNED,
+      g_param_spec_boolean ("accept-self-signed", "accept-self-signed",
+          "Accept self-signed SSL/TLS certificates",
+          DEFAULT_ACCEPT_SELF_SIGNED, G_PARAM_READWRITE));
+
 #ifndef GST_DISABLE_GST_DEBUG
   g_object_class_install_property
       (gobject_class, PROP_NEON_HTTP_DEBUG,
@@ -233,6 +241,7 @@ gst_neonhttp_src_init (GstNeonhttpSrc * src, GstNeonhttpSrcClass * g_class)
   src->iradio_url = DEFAULT_IRADIO_URL;
   src->user_agent = g_strdup (DEFAULT_USER_AGENT);
   src->automatic_redirect = DEFAULT_AUTOMATIC_REDIRECT;
+  src->accept_self_signed = DEFAULT_ACCEPT_SELF_SIGNED;
 
   src->session = NULL;
   src->request = NULL;
@@ -332,28 +341,23 @@ gst_neonhttp_src_set_property (GObject * object, guint prop_id,
       break;
     }
     case PROP_USER_AGENT:
-    {
       if (src->user_agent)
         g_free (src->user_agent);
       src->user_agent = g_strdup (g_value_get_string (value));
       break;
-    }
     case PROP_IRADIO_MODE:
-    {
       src->iradio_mode = g_value_get_boolean (value);
       break;
-    }
     case PROP_AUTOMATIC_REDIRECT:
-    {
       src->automatic_redirect = g_value_get_boolean (value);
       break;
-    }
+    case PROP_ACCEPT_SELF_SIGNED:
+      src->accept_self_signed = g_value_get_boolean (value);
+      break;
 #ifndef GST_DISABLE_GST_DEBUG
     case PROP_NEON_HTTP_DEBUG:
-    {
       src->neon_http_debug = g_value_get_boolean (value);
       break;
-    }
 #endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -401,10 +405,8 @@ gst_neonhttp_src_get_property (GObject * object, guint prop_id,
       break;
     }
     case PROP_USER_AGENT:
-    {
       g_value_set_string (value, neonhttpsrc->user_agent);
       break;
-    }
     case PROP_IRADIO_MODE:
       g_value_set_boolean (value, neonhttpsrc->iradio_mode);
       break;
@@ -420,6 +422,9 @@ gst_neonhttp_src_get_property (GObject * object, guint prop_id,
     case PROP_AUTOMATIC_REDIRECT:
       g_value_set_boolean (value, neonhttpsrc->automatic_redirect);
       break;
+    case PROP_ACCEPT_SELF_SIGNED:
+      g_value_set_boolean (value, neonhttpsrc->accept_self_signed);
+      break;
 #ifndef GST_DISABLE_GST_DEBUG
     case PROP_NEON_HTTP_DEBUG:
       g_value_set_boolean (value, neonhttpsrc->neon_http_debug);
@@ -431,6 +436,13 @@ gst_neonhttp_src_get_property (GObject * object, guint prop_id,
   }
 }
 
+/* NEON CALLBACK */
+static void
+oom_callback ()
+{
+  GST_ERROR ("memory exeception in neon");
+}
+
 static GstFlowReturn
 gst_neonhttp_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
 {
@@ -772,6 +784,37 @@ error:
   }
 }
 
+static int
+ssl_verify_callback (void *data, int failures, const ne_ssl_certificate * cert)
+{
+  GstNeonhttpSrc *src = GST_NEONHTTP_SRC (data);
+
+  if ((failures & NE_SSL_UNTRUSTED) &&
+      src->accept_self_signed && !ne_ssl_cert_signedby (cert)) {
+    GST_ELEMENT_INFO (src, RESOURCE, READ,
+        (NULL), ("Accepting self-signed server certificate"));
+
+    failures &= ~NE_SSL_UNTRUSTED;
+  }
+
+  if (failures & NE_SSL_NOTYETVALID)
+    GST_ELEMENT_ERROR (src, RESOURCE, READ,
+        (NULL), ("Server certificate not valid yet"));
+  if (failures & NE_SSL_EXPIRED)
+    GST_ELEMENT_ERROR (src, RESOURCE, READ,
+        (NULL), ("Server certificate has expired"));
+  if (failures & NE_SSL_IDMISMATCH)
+    GST_ELEMENT_ERROR (src, RESOURCE, READ,
+        (NULL), ("Server certificate doesn't match hostname"));
+  if (failures & NE_SSL_UNTRUSTED)
+    GST_ELEMENT_ERROR (src, RESOURCE, READ,
+        (NULL), ("Server certificate signer not trusted"));
+
+  GST_DEBUG_OBJECT (src, "failures: %d\n", failures);
+
+  return failures;
+}
+
 /* Try to send the HTTP request to the Icecast server, and if possible deals with
  * all the probable redirections (HTTP status code == 302/303)
  */
@@ -799,6 +842,7 @@ gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src,
     }
 
     ne_set_session_flag (session, NE_SESSFLAG_ICYPROTO, 1);
+    ne_ssl_set_verify (session, ssl_verify_callback, src);
 
     request = ne_request_create (session, "GET", src->query_string);
 
@@ -1014,13 +1058,6 @@ gst_neonhttp_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
   iface->set_uri = gst_neonhttp_src_uri_set_uri;
 }
 
-/* NEON CALLBACK */
-static void
-oom_callback ()
-{
-  GST_ERROR ("memory exeception in neon");
-}
-
 /* entry point to initialize the plug-in
  * initialize the plug-in itself
  * register the element factories and pad templates
index 6838348..f88c964 100644 (file)
@@ -71,6 +71,9 @@ struct _GstNeonhttpSrc {
   /* enable Neon HTTP debug messages */
   gboolean neon_http_debug;
 
+  /* accept self-signed certificates */
+  gboolean accept_self_signed;
+
   gint64 read_position;
   gboolean seekable;
 };