diff options
author | David Schleef <ds@schleef.org> | 2014-09-01 01:52:36 -0700 |
---|---|---|
committer | David Schleef <ds@schleef.org> | 2014-09-01 01:52:36 -0700 |
commit | 6fd24b0c5e6bab6a98af932cbca351b612264e04 (patch) | |
tree | 1de0aad30875538a4495b423bffc23b1c093efec | |
parent | ba84cd7539033ac7b6ef32751e9fcc720ed07d90 (diff) |
hacking. secureToken works
-rw-r--r-- | plugins/gstrtmp2src.c | 61 | ||||
-rw-r--r-- | plugins/gstrtmp2src.h | 1 | ||||
-rw-r--r-- | rtmp/amf.c | 8 | ||||
-rw-r--r-- | rtmp/amf.h | 1 | ||||
-rw-r--r-- | rtmp/rtmputils.c | 98 | ||||
-rw-r--r-- | rtmp/rtmputils.h | 3 |
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; @@ -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) { @@ -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 |