summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2014-09-01 01:52:36 -0700
committerDavid Schleef <ds@schleef.org>2014-09-01 01:52:36 -0700
commit6fd24b0c5e6bab6a98af932cbca351b612264e04 (patch)
tree1de0aad30875538a4495b423bffc23b1c093efec
parentba84cd7539033ac7b6ef32751e9fcc720ed07d90 (diff)
hacking. secureToken works
-rw-r--r--plugins/gstrtmp2src.c61
-rw-r--r--plugins/gstrtmp2src.h1
-rw-r--r--rtmp/amf.c8
-rw-r--r--rtmp/amf.h1
-rw-r--r--rtmp/rtmputils.c98
-rw-r--r--rtmp/rtmputils.h3
6 files changed, 169 insertions, 3 deletions
diff --git a/plugins/gstrtmp2src.c b/plugins/gstrtmp2src.c
index 2537fa6..4043b92 100644
--- a/plugins/gstrtmp2src.c
+++ b/plugins/gstrtmp2src.c
@@ -93,6 +93,8 @@ static void send_play (GstRtmp2Src * src);
static void play_done (GstRtmpConnection * connection, GstRtmpChunk * chunk,
const char *command_name, int transaction_id, GstAmfNode * command_object,
GstAmfNode * optional_args, gpointer user_data);
+static void send_secure_token_response (GstRtmp2Src * rtmp2src,
+ const char *challenge);
static gchar *gst_rtmp2_src_get_uri (GstRtmp2Src * src);
static gboolean gst_rtmp2_src_set_uri (GstRtmp2Src * src, const char *uri);
@@ -105,7 +107,8 @@ enum
PROP_SERVER_ADDRESS,
PROP_PORT,
PROP_APPLICATION,
- PROP_STREAM
+ PROP_STREAM,
+ PROP_SECURE_TOKEN
};
#define DEFAULT_LOCATION "rtmp://localhost/live/myStream"
@@ -114,6 +117,9 @@ enum
#define DEFAULT_PORT 1935
#define DEFAULT_APPLICATION "live"
#define DEFAULT_STREAM "myStream"
+//#define DEFAULT_SECURE_TOKEN ""
+/* FIXME for testing only */
+#define DEFAULT_SECURE_TOKEN "4305c027c2758beb"
/* pad templates */
@@ -129,10 +135,11 @@ GST_STATIC_PAD_TEMPLATE ("src",
G_DEFINE_TYPE_WITH_CODE (GstRtmp2Src, gst_rtmp2_src, GST_TYPE_PUSH_SRC,
do {
- G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
+ G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
gst_rtmp2_src_uri_handler_init);
GST_DEBUG_CATEGORY_INIT (gst_rtmp2_src_debug_category, "rtmp2src", 0,
- "debug category for rtmp2src element");} while (0));
+ "debug category for rtmp2src element");
+ } while (0));
static void
gst_rtmp2_src_class_init (GstRtmp2SrcClass * klass)
@@ -189,6 +196,10 @@ gst_rtmp2_src_class_init (GstRtmp2SrcClass * klass)
g_param_spec_string ("stream", "RTMP stream",
"RTMP stream",
DEFAULT_STREAM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_SECURE_TOKEN,
+ g_param_spec_string ("secure-token", "Secure token",
+ "Secure token used for authentication",
+ DEFAULT_SECURE_TOKEN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
@@ -202,6 +213,7 @@ gst_rtmp2_src_init (GstRtmp2Src * rtmp2src)
rtmp2src->timeout = DEFAULT_TIMEOUT;
gst_rtmp2_src_set_uri (rtmp2src, DEFAULT_LOCATION);
+ rtmp2src->secure_token = g_strdup (DEFAULT_SECURE_TOKEN);
rtmp2src->task = gst_task_new (gst_rtmp2_src_task, rtmp2src, NULL);
g_rec_mutex_init (&rtmp2src->task_lock);
@@ -288,6 +300,10 @@ gst_rtmp2_src_set_property (GObject * object, guint property_id,
g_free (rtmp2src->stream);
rtmp2src->stream = g_value_dup_string (value);
break;
+ case PROP_SECURE_TOKEN:
+ g_free (rtmp2src->secure_token);
+ rtmp2src->secure_token = g_value_dup_string (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -318,6 +334,9 @@ gst_rtmp2_src_get_property (GObject * object, guint property_id,
case PROP_STREAM:
g_value_set_string (value, rtmp2src->stream);
break;
+ case PROP_SECURE_TOKEN:
+ g_value_set_string (value, rtmp2src->secure_token);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -515,8 +534,18 @@ cmd_connect_done (GstRtmpConnection * connection, GstRtmpChunk * chunk,
}
if (ret) {
+ const GstAmfNode *n;
+
GST_DEBUG ("success");
+ n = gst_amf_node_get_object (optional_args, "secureToken");
+ if (n) {
+ const gchar *challenge;
+ challenge = gst_amf_node_get_string (n);
+ GST_DEBUG ("secureToken challenge: %s", challenge);
+ send_secure_token_response (rtmp2src, challenge);
+ }
+
send_create_stream (rtmp2src);
} else {
GST_ERROR ("connect error");
@@ -851,3 +880,29 @@ out:
g_strfreev (parts);
return ret;
}
+
+static void
+send_secure_token_response (GstRtmp2Src * rtmp2src, const char *challenge)
+{
+ GstAmfNode *node1;
+ GstAmfNode *node2;
+ gchar *response;
+
+ if (rtmp2src->secure_token == NULL || !rtmp2src->secure_token[0]) {
+ GST_ELEMENT_ERROR (rtmp2src, RESOURCE, OPEN_READ,
+ ("Server requested secureToken authentication"), (NULL));
+ return;
+ }
+
+ response = gst_rtmp_tea_decode (rtmp2src->secure_token, challenge);
+
+ GST_DEBUG ("response: %s", response);
+
+ node1 = gst_amf_node_new (GST_AMF_TYPE_NULL);
+ node2 = gst_amf_node_new (GST_AMF_TYPE_STRING);
+ gst_amf_node_set_string_take (node2, response);
+
+ gst_rtmp_connection_send_command (rtmp2src->connection, 3,
+ "secureTokenResponse", 0, node1, node2, NULL, NULL);
+
+}
diff --git a/plugins/gstrtmp2src.h b/plugins/gstrtmp2src.h
index ab1eea6..64f7f3f 100644
--- a/plugins/gstrtmp2src.h
+++ b/plugins/gstrtmp2src.h
@@ -46,6 +46,7 @@ struct _GstRtmp2Src
int port;
char *application;
char *stream;
+ char *secure_token;
/* stuff */
gboolean sent_header;
diff --git a/rtmp/amf.c b/rtmp/amf.c
index c942fea..b8a556c 100644
--- a/rtmp/amf.c
+++ b/rtmp/amf.c
@@ -299,6 +299,14 @@ gst_amf_node_set_string_take (GstAmfNode * node, char *s)
}
void
+gst_amf_node_set_binary_string_take (GstAmfNode * node, guint8 * s, gsize size)
+{
+ g_return_if_fail (node->type == GST_AMF_TYPE_STRING);
+ /* FIXME this needs to take NUL chars in string */
+ node->string_val = (gchar *) s;
+}
+
+void
gst_amf_object_append_take (GstAmfNode * node, const char *s,
GstAmfNode * child_node)
{
diff --git a/rtmp/amf.h b/rtmp/amf.h
index 4ab9676..859c7d2 100644
--- a/rtmp/amf.h
+++ b/rtmp/amf.h
@@ -65,6 +65,7 @@ GstAmfNode * gst_amf_node_new_parse (const guint8 *data, gsize size,
void gst_amf_node_set_boolean (GstAmfNode *node, gboolean val);
void gst_amf_node_set_number (GstAmfNode *node, double val);
void gst_amf_node_set_string (GstAmfNode *node, const char *s);
+void gst_amf_node_set_binary_string_take (GstAmfNode *node, guint8 *s, gsize size);
void gst_amf_node_set_string_take (GstAmfNode *node, char *s);
void gst_amf_node_set_ecma_array (GstAmfNode *node, guint8 *data, int size);
void gst_amf_object_append_take (GstAmfNode *node, const char *s,
diff --git a/rtmp/rtmputils.c b/rtmp/rtmputils.c
index cb0474f..c479680 100644
--- a/rtmp/rtmputils.c
+++ b/rtmp/rtmputils.c
@@ -21,6 +21,8 @@
#include "config.h"
#endif
+#include <gst/gst.h>
+
#include "rtmputils.h"
#include <string.h>
@@ -82,3 +84,99 @@ gst_rtmp_bytes_remove (GBytes * bytes, gsize size)
return new_bytes;
}
+
+gchar *
+gst_rtmp_hexify (const guint8 * src, gsize size)
+{
+ static const char xdigit[] = "0123456789abcdef";
+ int i;
+ gchar *dest;
+ dest = g_malloc (2 * size + 1);
+ for (i = 0; i < size; i++) {
+ dest[2 * i] = xdigit[src[i] >> 4];
+ dest[2 * i + 1] = xdigit[src[i] & 0xf];
+ }
+ dest[2 * size] = 0;
+ return dest;
+}
+
+guint8 *
+gst_rtmp_unhexify (const char *src, gsize * size)
+{
+ int i, n;
+ guint8 *dest;
+ n = strlen (src) / 2;
+ dest = g_malloc (n + 1);
+ for (i = 0; i < n; i++) {
+ dest[i] = g_ascii_xdigit_value (src[2 * i]) << 4 |
+ g_ascii_xdigit_value (src[2 * i + 1]);
+ }
+ dest[n] = 0;
+ if (size)
+ *size = n;
+ return dest;
+}
+
+/* taken from librtmp */
+gchar *
+gst_rtmp_tea_decode (const gchar * key, const gchar * text)
+{
+ guint32 *v, k[4] = { 0 }, u;
+ guint32 z, y, sum = 0, e, DELTA = 0x9e3779b9;
+ gint32 p, q;
+ int i, n;
+ unsigned char *ptr, *out;
+
+ /* prep key: pack 1st 16 chars into 4 LittleEndian ints */
+ ptr = (unsigned char *) key;
+ u = 0;
+ n = 0;
+ v = k;
+ p = strlen (key) > 16 ? 16 : strlen (key);
+ for (i = 0; i < p; i++) {
+ u |= ptr[i] << (n * 8);
+ if (n == 3) {
+ *v++ = u;
+ u = 0;
+ n = 0;
+ } else {
+ n++;
+ }
+ }
+ /* any trailing chars */
+ if (u)
+ *v = u;
+
+ /* prep text: hex2bin, multiples of 4 */
+ n = (strlen (text) + 7) / 8;
+ out = malloc (n * 8);
+ ptr = (unsigned char *) text;
+ v = (guint32 *) out;
+ for (i = 0; i < n; i++) {
+#define HEX2BIN(x) g_ascii_xdigit_value(x)
+ u = (HEX2BIN (ptr[0]) << 4) + HEX2BIN (ptr[1]);
+ u |= ((HEX2BIN (ptr[2]) << 4) + HEX2BIN (ptr[3])) << 8;
+ u |= ((HEX2BIN (ptr[4]) << 4) + HEX2BIN (ptr[5])) << 16;
+ u |= ((HEX2BIN (ptr[6]) << 4) + HEX2BIN (ptr[7])) << 24;
+ *v++ = u;
+ ptr += 8;
+ }
+ v = (guint32 *) out;
+
+ /* http://www.movable-type.co.uk/scripts/tea-block.html */
+#define MX (((z>>5)^(y<<2)) + ((y>>3)^(z<<4))) ^ ((sum^y) + (k[(p&3)^e]^z));
+ z = v[n - 1];
+ y = v[0];
+ q = 6 + 52 / n;
+ sum = q * DELTA;
+ while (sum != 0) {
+ e = sum >> 2 & 3;
+ for (p = n - 1; p > 0; p--)
+ z = v[p - 1], y = v[p] -= MX;
+ z = v[n - 1];
+ y = v[0] -= MX;
+ sum -= DELTA;
+ }
+
+ return (gchar *) out;
+}
diff --git a/rtmp/rtmputils.h b/rtmp/rtmputils.h
index 2a58f82..b020367 100644
--- a/rtmp/rtmputils.h
+++ b/rtmp/rtmputils.h
@@ -27,6 +27,9 @@ G_BEGIN_DECLS
void gst_rtmp_dump_data (GBytes * bytes);
GBytes *gst_rtmp_bytes_append (GBytes *bytes, guint8 *data, gsize size);
GBytes *gst_rtmp_bytes_remove (GBytes *bytes, gsize size);
+gchar * gst_rtmp_hexify (const guint8 *src, gsize size);
+guint8 * gst_rtmp_unhexify (const char *src, gsize *size);
+gchar * gst_rtmp_tea_decode (const gchar *key, const gchar *text);
G_END_DECLS