diff --git a/examples/test-auth.c b/examples/test-auth.c index ee8af5728f..f5a129ca8b 100644 --- a/examples/test-auth.c +++ b/examples/test-auth.c @@ -87,16 +87,6 @@ main (int argc, char *argv[]) "audiotestsrc ! audio/x-raw,rate=8000 ! " "alawenc ! rtppcmapay name=pay1 pt=97 " ")"); - /* make a new authentication manager */ - auth = gst_rtsp_auth_new (); - basic = gst_rtsp_auth_make_basic ("user", "password"); - gst_rtsp_auth_add_basic (auth, basic, "user"); - g_free (basic); - basic = gst_rtsp_auth_make_basic ("admin", "power"); - gst_rtsp_auth_add_basic (auth, basic, "admin"); - g_free (basic); - gst_rtsp_media_factory_set_auth (factory, auth); - g_object_unref (auth); /* attach the test factory to the /test url */ gst_rtsp_mount_points_add_factory (mounts, "/test", factory); @@ -105,19 +95,27 @@ main (int argc, char *argv[]) gst_rtsp_media_factory_set_launch (factory, "( " "videotestsrc ! video/x-raw,width=352,height=288,framerate=30/1 ! " "x264enc ! rtph264pay name=pay0 pt=96 )"); - /* make a new authentication manager */ - auth = gst_rtsp_auth_new (); - basic = gst_rtsp_auth_make_basic ("admin2", "power2"); - gst_rtsp_auth_add_basic (auth, basic, "admin"); - g_free (basic); - gst_rtsp_media_factory_set_auth (factory, auth); - g_object_unref (auth); /* attach the test factory to the /test url */ gst_rtsp_mount_points_add_factory (mounts, "/test2", factory); /* don't need the ref to the mapper anymore */ g_object_unref (mounts); + /* make a new authentication manager */ + auth = gst_rtsp_auth_new (); + basic = gst_rtsp_auth_make_basic ("user", "password"); + gst_rtsp_auth_add_basic (auth, basic, "user"); + g_free (basic); + basic = gst_rtsp_auth_make_basic ("admin", "power"); + gst_rtsp_auth_add_basic (auth, basic, "admin"); + g_free (basic); + basic = gst_rtsp_auth_make_basic ("admin2", "power2"); + gst_rtsp_auth_add_basic (auth, basic, "admin"); + g_free (basic); + /* set as the server authentication manager */ + gst_rtsp_server_set_auth (server, auth); + g_object_unref (auth); + /* attach the server to the default maincontext */ if (gst_rtsp_server_attach (server, NULL) == 0) goto failed; diff --git a/gst/rtsp-server/rtsp-auth.c b/gst/rtsp-server/rtsp-auth.c index 6ed627fd68..a0df870788 100644 --- a/gst/rtsp-server/rtsp-auth.c +++ b/gst/rtsp-server/rtsp-auth.c @@ -46,10 +46,12 @@ static void gst_rtsp_auth_set_property (GObject * object, guint propid, const GValue * value, GParamSpec * pspec); static void gst_rtsp_auth_finalize (GObject * obj); -static gboolean default_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client, +static gboolean default_setup (GstRTSPAuth * auth, GstRTSPClient * client, + GstRTSPClientState * state); +static gboolean default_validate (GstRTSPAuth * auth, + GstRTSPClient * client, GstRTSPClientState * state); +static gboolean default_check (GstRTSPAuth * auth, GstRTSPClient * client, GQuark hint, GstRTSPClientState * state); -static gboolean default_check_method (GstRTSPAuth * auth, - GstRTSPClient * client, GQuark hint, GstRTSPClientState * state); G_DEFINE_TYPE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT); @@ -66,8 +68,9 @@ gst_rtsp_auth_class_init (GstRTSPAuthClass * klass) gobject_class->set_property = gst_rtsp_auth_set_property; gobject_class->finalize = gst_rtsp_auth_finalize; - klass->setup_auth = default_setup_auth; - klass->check_method = default_check_method; + klass->setup = default_setup; + klass->validate = default_validate; + klass->check = default_check; GST_DEBUG_CATEGORY_INIT (rtsp_auth_debug, "rtspauth", 0, "GstRTSPAuth"); } @@ -192,8 +195,8 @@ gst_rtsp_auth_remove_basic (GstRTSPAuth * auth, const gchar * basic) } static gboolean -default_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client, - GQuark hint, GstRTSPClientState * state) +default_setup (GstRTSPAuth * auth, GstRTSPClient * client, + GstRTSPClientState * state) { if (state->response == NULL) return FALSE; @@ -206,10 +209,9 @@ default_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client, } /** - * gst_rtsp_auth_setup_auth: + * gst_rtsp_auth_setup: * @auth: a #GstRTSPAuth * @client: the client - * @hint: TODO * @state: TODO * * Add authentication tokens to @response. @@ -217,8 +219,8 @@ default_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client, * Returns: FALSE if something is wrong. */ gboolean -gst_rtsp_auth_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client, - GQuark hint, GstRTSPClientState * state) +gst_rtsp_auth_setup (GstRTSPAuth * auth, GstRTSPClient * client, + GstRTSPClientState * state) { gboolean result = FALSE; GstRTSPAuthClass *klass; @@ -231,53 +233,83 @@ gst_rtsp_auth_setup_auth (GstRTSPAuth * auth, GstRTSPClient * client, GST_DEBUG_OBJECT (auth, "setup auth"); - if (klass->setup_auth) - result = klass->setup_auth (auth, client, hint, state); + if (klass->setup) + result = klass->setup (auth, client, state); return result; } static gboolean -default_check_method (GstRTSPAuth * auth, GstRTSPClient * client, - GQuark hint, GstRTSPClientState * state) +default_validate (GstRTSPAuth * auth, GstRTSPClient * client, + GstRTSPClientState * state) { GstRTSPAuthPrivate *priv = auth->priv; - gboolean result = TRUE; GstRTSPResult res; + gchar *authorization; - if ((state->method & priv->methods) != 0) { - gchar *authorization; + GST_DEBUG_OBJECT (auth, "validate"); - result = FALSE; + res = + gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_AUTHORIZATION, + &authorization, 0); + if (res < 0) + goto no_auth; - res = - gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_AUTHORIZATION, - &authorization, 0); - if (res < 0) - goto no_auth; + /* parse type */ + if (g_ascii_strncasecmp (authorization, "basic ", 6) == 0) { + gchar *authgroup; - /* parse type */ - if (g_ascii_strncasecmp (authorization, "basic ", 6) == 0) { - gchar *authgroup; - - GST_DEBUG_OBJECT (auth, "check Basic auth"); - g_mutex_lock (&priv->lock); - if ((authgroup = g_hash_table_lookup (priv->basic, &authorization[6]))) { - result = TRUE; - state->authgroup = authgroup; - } - g_mutex_unlock (&priv->lock); - } else if (g_ascii_strncasecmp (authorization, "digest ", 7) == 0) { - GST_DEBUG_OBJECT (auth, "check Digest auth"); - /* not implemented yet */ - result = FALSE; + GST_DEBUG_OBJECT (auth, "check Basic auth"); + g_mutex_lock (&priv->lock); + if ((authgroup = g_hash_table_lookup (priv->basic, &authorization[6]))) { + GST_DEBUG_OBJECT (auth, "setting authgroup %s", authgroup); + state->authgroup = authgroup; } + g_mutex_unlock (&priv->lock); + } else if (g_ascii_strncasecmp (authorization, "digest ", 7) == 0) { + GST_DEBUG_OBJECT (auth, "check Digest auth"); + /* not implemented yet */ } - return result; + return TRUE; no_auth: { GST_DEBUG_OBJECT (auth, "no authorization header found"); + return TRUE; + } +} + +static gboolean +default_check (GstRTSPAuth * auth, GstRTSPClient * client, + GQuark hint, GstRTSPClientState * state) +{ + GstRTSPAuthPrivate *priv = auth->priv; + GstRTSPAuthClass *klass; + + klass = GST_RTSP_AUTH_GET_CLASS (auth); + + if ((state->method & priv->methods) != 0) { + /* we need an authgroup to check */ + if (state->authgroup == NULL) { + if (klass->validate) { + if (!klass->validate (auth, client, state)) + goto validate_failed; + } + } + + if (state->authgroup == NULL) + goto no_auth; + } + return TRUE; + +validate_failed: + { + GST_DEBUG_OBJECT (auth, "validation failed"); + return FALSE; + } +no_auth: + { + GST_DEBUG_OBJECT (auth, "no authorization group found"); return FALSE; } } @@ -289,9 +321,10 @@ no_auth: * @hint: a hint * @state: client state * - * Check if @client is allowed to perform the actions of @state. + * Check if @client with state is authorized to perform @hint in the + * current @state. * - * Returns: FALSE if the action is not allowed. + * Returns: FALSE if check failed. */ gboolean gst_rtsp_auth_check (GstRTSPAuth * auth, GstRTSPClient * client, @@ -306,10 +339,10 @@ gst_rtsp_auth_check (GstRTSPAuth * auth, GstRTSPClient * client, klass = GST_RTSP_AUTH_GET_CLASS (auth); - GST_DEBUG_OBJECT (auth, "check state"); + GST_DEBUG_OBJECT (auth, "check auth"); - if (klass->check_method) - result = klass->check_method (auth, client, hint, state); + if (klass->check) + result = klass->check (auth, client, hint, state); return result; } diff --git a/gst/rtsp-server/rtsp-auth.h b/gst/rtsp-server/rtsp-auth.h index 425413b3c3..fd9b679a5a 100644 --- a/gst/rtsp-server/rtsp-auth.h +++ b/gst/rtsp-server/rtsp-auth.h @@ -53,10 +53,12 @@ struct _GstRTSPAuth { struct _GstRTSPAuthClass { GObjectClass parent_class; - gboolean (*setup_auth) (GstRTSPAuth *auth, GstRTSPClient * client, - GQuark hint, GstRTSPClientState *state); - gboolean (*check_method) (GstRTSPAuth *auth, GstRTSPClient * client, - GQuark hint, GstRTSPClientState *state); + gboolean (*setup) (GstRTSPAuth *auth, GstRTSPClient * client, + GstRTSPClientState *state); + gboolean (*validate) (GstRTSPAuth *auth, GstRTSPClient * client, + GstRTSPClientState *state); + gboolean (*check) (GstRTSPAuth *auth, GstRTSPClient * client, + GQuark hint, GstRTSPClientState *state); }; GType gst_rtsp_auth_get_type (void); @@ -67,10 +69,12 @@ void gst_rtsp_auth_add_basic (GstRTSPAuth *auth, const gc const gchar *authgroup); void gst_rtsp_auth_remove_basic (GstRTSPAuth *auth, const gchar * basic); -gboolean gst_rtsp_auth_setup_auth (GstRTSPAuth *auth, GstRTSPClient * client, - GQuark hint, GstRTSPClientState *state); +gboolean gst_rtsp_auth_setup (GstRTSPAuth *auth, GstRTSPClient * client, + GstRTSPClientState *state); + gboolean gst_rtsp_auth_check (GstRTSPAuth *auth, GstRTSPClient * client, GQuark hint, GstRTSPClientState *state); + /* helpers */ gchar * gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass); diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c index db821746de..a597916227 100644 --- a/gst/rtsp-server/rtsp-client.c +++ b/gst/rtsp-server/rtsp-client.c @@ -456,7 +456,7 @@ handle_unauthorized_request (GstRTSPClient * client, GstRTSPAuth * auth, if (auth) { /* and let the authentication manager setup the auth tokens */ - gst_rtsp_auth_setup_auth (auth, client, 0, state); + gst_rtsp_auth_setup (auth, client, state); } send_message (client, state->session, state->response, FALSE); @@ -487,7 +487,6 @@ find_media (GstRTSPClient * client, GstRTSPClientState * state, gint * matched) GstRTSPClientPrivate *priv = client->priv; GstRTSPMediaFactory *factory; GstRTSPMedia *media; - GstRTSPAuth *auth; gchar *path; gint path_len; @@ -518,17 +517,6 @@ find_media (GstRTSPClient * client, GstRTSPClientState * state, gint * matched) } priv->media = NULL; - /* check if we have access to the factory */ - if ((auth = gst_rtsp_media_factory_get_auth (factory))) { - state->factory = factory; - - if (!gst_rtsp_auth_check (auth, client, 0, state)) - goto not_allowed; - - state->factory = NULL; - g_object_unref (auth); - } - /* prepare the media and add it to the pipeline */ if (!(media = gst_rtsp_media_factory_construct (factory, state->uri))) goto no_media; @@ -568,15 +556,6 @@ no_factory: send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state); return NULL; } -not_allowed: - { - GST_ERROR ("client %p: unauthorized request", client); - handle_unauthorized_request (client, auth, state); - g_object_unref (factory); - state->factory = NULL; - g_object_unref (auth); - return NULL; - } no_media: { GST_ERROR ("client %p: can't create media", client); @@ -1847,6 +1826,8 @@ handle_request (GstRTSPClient * client, GstRTSPMessage * request) if (priv->auth) { if (!gst_rtsp_auth_check (priv->auth, client, 0, &state)) goto not_authorized; + + state.auth = priv->auth; } /* now see what is asked and dispatch to a dedicated handler */ diff --git a/gst/rtsp-server/rtsp-client.h b/gst/rtsp-server/rtsp-client.h index b5adc104f3..86ae980ed6 100644 --- a/gst/rtsp-server/rtsp-client.h +++ b/gst/rtsp-server/rtsp-client.h @@ -65,6 +65,7 @@ struct _GstRTSPClientState { GstRTSPMessage *request; GstRTSPUrl *uri; GstRTSPMethod method; + GstRTSPAuth *auth; const gchar *authgroup; GstRTSPSession *session; GstRTSPSessionMedia *sessmedia; diff --git a/gst/rtsp-server/rtsp-media-factory.c b/gst/rtsp-server/rtsp-media-factory.c index f448276276..b6fa8c033f 100644 --- a/gst/rtsp-server/rtsp-media-factory.c +++ b/gst/rtsp-server/rtsp-media-factory.c @@ -33,7 +33,6 @@ struct _GstRTSPMediaFactoryPrivate gboolean shared; gboolean eos_shutdown; GstRTSPLowerTrans protocols; - GstRTSPAuth *auth; guint buffer_size; GstRTSPAddressPool *pool; @@ -194,8 +193,6 @@ gst_rtsp_media_factory_finalize (GObject * obj) g_mutex_clear (&priv->medias_lock); g_free (priv->launch); g_mutex_clear (&priv->lock); - if (priv->auth) - g_object_unref (priv->auth); if (priv->pool) g_object_unref (priv->pool); @@ -535,62 +532,6 @@ gst_rtsp_media_factory_get_address_pool (GstRTSPMediaFactory * factory) return result; } -/** - * gst_rtsp_media_factory_set_auth: - * @factory: a #GstRTSPMediaFactory - * @auth: a #GstRTSPAuth - * - * configure @auth to be used as the authentication manager of @factory. - */ -void -gst_rtsp_media_factory_set_auth (GstRTSPMediaFactory * factory, - GstRTSPAuth * auth) -{ - GstRTSPMediaFactoryPrivate *priv; - GstRTSPAuth *old; - - g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); - - priv = factory->priv; - - GST_RTSP_MEDIA_FACTORY_LOCK (factory); - if ((old = priv->auth) != auth) - priv->auth = auth ? g_object_ref (auth) : NULL; - else - old = NULL; - GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); - - if (old) - g_object_unref (old); -} - -/** - * gst_rtsp_media_factory_get_auth: - * @factory: a #GstRTSPMediaFactory - * - * Get the #GstRTSPAuth used as the authentication manager of @factory. - * - * Returns: (transfer full): the #GstRTSPAuth of @factory. g_object_unref() after - * usage. - */ -GstRTSPAuth * -gst_rtsp_media_factory_get_auth (GstRTSPMediaFactory * factory) -{ - GstRTSPMediaFactoryPrivate *priv; - GstRTSPAuth *result; - - g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), NULL); - - priv = factory->priv; - - GST_RTSP_MEDIA_FACTORY_LOCK (factory); - if ((result = priv->auth)) - g_object_ref (result); - GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); - - return result; -} - /** * gst_rtsp_media_factory_set_protocols: * @factory: a #GstRTSPMediaFactory @@ -896,7 +837,6 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media) GstRTSPMediaFactoryPrivate *priv = factory->priv; gboolean shared, eos_shutdown; guint size; - GstRTSPAuth *auth; GstRTSPLowerTrans protocols; GstRTSPAddressPool *pool; @@ -913,10 +853,6 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media) gst_rtsp_media_set_buffer_size (media, size); gst_rtsp_media_set_protocols (media, protocols); - if ((auth = gst_rtsp_media_factory_get_auth (factory))) { - gst_rtsp_media_set_auth (media, auth); - g_object_unref (auth); - } if ((pool = gst_rtsp_media_factory_get_address_pool (factory))) { gst_rtsp_media_set_address_pool (media, pool); g_object_unref (pool); diff --git a/gst/rtsp-server/rtsp-media-factory.h b/gst/rtsp-server/rtsp-media-factory.h index d974fa0148..a492422e38 100644 --- a/gst/rtsp-server/rtsp-media-factory.h +++ b/gst/rtsp-server/rtsp-media-factory.h @@ -114,9 +114,6 @@ gboolean gst_rtsp_media_factory_is_eos_shutdown (GstRTSPMediaFac void gst_rtsp_media_factory_set_protocols (GstRTSPMediaFactory *factory, GstRTSPLowerTrans protocols); GstRTSPLowerTrans gst_rtsp_media_factory_get_protocols (GstRTSPMediaFactory *factory); -void gst_rtsp_media_factory_set_auth (GstRTSPMediaFactory *factory, GstRTSPAuth *auth); -GstRTSPAuth * gst_rtsp_media_factory_get_auth (GstRTSPMediaFactory *factory); - void gst_rtsp_media_factory_set_address_pool (GstRTSPMediaFactory * factory, GstRTSPAddressPool * pool); GstRTSPAddressPool * gst_rtsp_media_factory_get_address_pool (GstRTSPMediaFactory * factory); diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index d20087dbbd..4e25e1584f 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -40,7 +40,6 @@ struct _GstRTSPMediaPrivate gboolean reused; gboolean eos_shutdown; guint buffer_size; - GstRTSPAuth *auth; GstRTSPAddressPool *pool; GstElement *element; @@ -262,8 +261,6 @@ gst_rtsp_media_finalize (GObject * obj) if (priv->nettime) gst_object_unref (priv->nettime); gst_object_unref (priv->element); - if (priv->auth) - g_object_unref (priv->auth); if (priv->pool) g_object_unref (priv->pool); g_mutex_clear (&priv->lock); @@ -784,63 +781,6 @@ gst_rtsp_media_is_time_provider (GstRTSPMedia * media) return res; } -/** - * gst_rtsp_media_set_auth: - * @media: a #GstRTSPMedia - * @auth: a #GstRTSPAuth - * - * configure @auth to be used as the authentication manager of @media. - */ -void -gst_rtsp_media_set_auth (GstRTSPMedia * media, GstRTSPAuth * auth) -{ - GstRTSPMediaPrivate *priv; - GstRTSPAuth *old; - - g_return_if_fail (GST_IS_RTSP_MEDIA (media)); - - priv = media->priv; - - GST_LOG_OBJECT (media, "set auth %p", auth); - - g_mutex_lock (&priv->lock); - if ((old = priv->auth) != auth) - priv->auth = auth ? g_object_ref (auth) : NULL; - else - old = NULL; - g_mutex_unlock (&priv->lock); - - if (old) - g_object_unref (old); -} - -/** - * gst_rtsp_media_get_auth: - * @media: a #GstRTSPMedia - * - * Get the #GstRTSPAuth used as the authentication manager of @media. - * - * Returns: (transfer full): the #GstRTSPAuth of @media. g_object_unref() after - * usage. - */ -GstRTSPAuth * -gst_rtsp_media_get_auth (GstRTSPMedia * media) -{ - GstRTSPMediaPrivate *priv; - GstRTSPAuth *result; - - g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); - - priv = media->priv; - - g_mutex_lock (&priv->lock); - if ((result = priv->auth)) - g_object_ref (result); - g_mutex_unlock (&priv->lock); - - return result; -} - /** * gst_rtsp_media_set_address_pool: * @media: a #GstRTSPMedia diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h index d6d2153864..02be092c7e 100644 --- a/gst/rtsp-server/rtsp-media.h +++ b/gst/rtsp-server/rtsp-media.h @@ -137,9 +137,6 @@ GstRTSPLowerTrans gst_rtsp_media_get_protocols (GstRTSPMedia *media); void gst_rtsp_media_set_eos_shutdown (GstRTSPMedia *media, gboolean eos_shutdown); gboolean gst_rtsp_media_is_eos_shutdown (GstRTSPMedia *media); -void gst_rtsp_media_set_auth (GstRTSPMedia *media, GstRTSPAuth *auth); -GstRTSPAuth * gst_rtsp_media_get_auth (GstRTSPMedia *media); - void gst_rtsp_media_set_address_pool (GstRTSPMedia *media, GstRTSPAddressPool *pool); GstRTSPAddressPool * gst_rtsp_media_get_address_pool (GstRTSPMedia *media);