From: Wim Taymans Date: Fri, 12 Jul 2013 13:19:29 +0000 (+0200) Subject: auth: handle unauthorized response X-Git-Tag: 1.19.3~495^2~1037 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5cf75e64af9a9d5b5e5b5cda577a75767c912ad4;p=platform%2Fupstream%2Fgstreamer.git auth: handle unauthorized response Move handling of the unauthorized response to the auth module, it can add the appropriate headers to request authorization for the required method much better than the client. --- diff --git a/gst/rtsp-server/rtsp-auth.c b/gst/rtsp-server/rtsp-auth.c index f5afb97..f7386a7 100644 --- a/gst/rtsp-server/rtsp-auth.c +++ b/gst/rtsp-server/rtsp-auth.c @@ -56,7 +56,6 @@ 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 (GstRTSPAuth * auth, GstRTSPClientState * state); static gboolean default_authenticate (GstRTSPAuth * auth, GstRTSPClientState * state); static gboolean default_check (GstRTSPAuth * auth, GstRTSPClientState * state, @@ -77,7 +76,6 @@ 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 = default_setup; klass->authenticate = default_authenticate; klass->check = default_check; @@ -267,47 +265,6 @@ gst_rtsp_auth_remove_basic (GstRTSPAuth * auth, const gchar * basic) } static gboolean -default_setup (GstRTSPAuth * auth, GstRTSPClientState * state) -{ - if (state->response == NULL) - return FALSE; - - /* we only have Basic for now */ - gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_WWW_AUTHENTICATE, - "Basic realm=\"GStreamer RTSP Server\""); - - return TRUE; -} - -/** - * gst_rtsp_auth_setup: - * @auth: a #GstRTSPAuth - * @state: the client state - * - * Add authentication tokens to @response in @state. - * - * Returns: FALSE if something is wrong. - */ -gboolean -gst_rtsp_auth_setup (GstRTSPAuth * auth, GstRTSPClientState * state) -{ - gboolean result = FALSE; - GstRTSPAuthClass *klass; - - g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), FALSE); - g_return_val_if_fail (state != NULL, FALSE); - - klass = GST_RTSP_AUTH_GET_CLASS (auth); - - GST_DEBUG_OBJECT (auth, "setup auth"); - - if (klass->setup) - result = klass->setup (auth, state); - - return result; -} - -static gboolean default_authenticate (GstRTSPAuth * auth, GstRTSPClientState * state) { GstRTSPAuthPrivate *priv = auth->priv; @@ -378,51 +335,124 @@ no_auth: } } +static void +send_response (GstRTSPAuth * auth, GstRTSPStatusCode code, + GstRTSPClientState * state) +{ + gst_rtsp_message_init_response (state->response, code, + gst_rtsp_status_as_text (code), state->request); + + if (code == GST_RTSP_STS_UNAUTHORIZED) { + /* we only have Basic for now */ + gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_WWW_AUTHENTICATE, + "Basic realm=\"GStreamer RTSP Server\""); + } + gst_rtsp_client_send_message (state->client, state->session, state->response); +} + +/* new connection */ static gboolean -default_check (GstRTSPAuth * auth, GstRTSPClientState * state, +check_connect (GstRTSPAuth * auth, GstRTSPClientState * state, const gchar * check) { GstRTSPAuthPrivate *priv = auth->priv; + + if (priv->certificate) { + GTlsConnection *tls; + + /* configure the connection */ + tls = gst_rtsp_connection_get_tls (state->conn, NULL); + g_tls_connection_set_certificate (tls, priv->certificate); + } + return TRUE; +} + +/* check url and methods */ +static gboolean +check_url (GstRTSPAuth * auth, GstRTSPClientState * state, const gchar * check) +{ + GstRTSPAuthPrivate *priv = auth->priv; + + if ((state->method & priv->methods) != 0) + if (!ensure_authenticated (auth, state)) + goto not_authenticated; + + return TRUE; + + /* ERRORS */ +not_authenticated: + { + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, state); + return FALSE; + } +} + +/* check access to media factory */ +static gboolean +check_factory (GstRTSPAuth * auth, GstRTSPClientState * state, + const gchar * check) +{ + const gchar *role; + GstRTSPPermissions *perms; + + if (!(role = gst_rtsp_token_get_string (state->token, + GST_RTSP_MEDIA_FACTORY_ROLE))) + goto no_media_role; + if (!(perms = gst_rtsp_media_factory_get_permissions (state->factory))) + goto no_permissions; + + if (g_str_equal (check, "auth.check.media.factory.access")) { + if (!gst_rtsp_permissions_is_allowed (perms, role, + GST_RTSP_MEDIA_FACTORY_PERM_ACCESS)) + goto no_access; + } else if (g_str_equal (check, "auth.check.media.factory.construct")) { + if (gst_rtsp_permissions_is_allowed (perms, role, + GST_RTSP_MEDIA_FACTORY_PERM_CONSTRUCT)) + goto no_construct; + } + return TRUE; + + /* ERRORS */ +no_media_role: + { + GST_DEBUG_OBJECT (auth, "no media factory role found"); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, state); + return FALSE; + } +no_permissions: + { + GST_DEBUG_OBJECT (auth, "no permissions on media factory found"); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, state); + return FALSE; + } +no_access: + { + GST_DEBUG_OBJECT (auth, "no permissions to access media factory"); + send_response (auth, GST_RTSP_STS_NOT_FOUND, state); + return FALSE; + } +no_construct: + { + GST_DEBUG_OBJECT (auth, "no permissions to construct media factory"); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, state); + return FALSE; + } +} + +static gboolean +default_check (GstRTSPAuth * auth, GstRTSPClientState * state, + const gchar * check) +{ gboolean res = FALSE; + /* FIXME, use hastable or so */ if (g_str_equal (check, GST_RTSP_AUTH_CHECK_CONNECT)) { - /* new connection */ - if (priv->certificate) { - GTlsConnection *tls; - - /* configure the connection */ - tls = gst_rtsp_connection_get_tls (state->conn, NULL); - g_tls_connection_set_certificate (tls, priv->certificate); - } - res = TRUE; + res = check_connect (auth, state, check); } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_URL)) { - /* check url and methods */ - if ((state->method & priv->methods) != 0) - res = ensure_authenticated (auth, state); - else - res = TRUE; + res = check_url (auth, state, check); } else if (g_str_has_prefix (check, "auth.check.media.factory.")) { - /* check access to media factory */ - const gchar *role; - GstRTSPPermissions *perms; - - if (!(role = - gst_rtsp_token_get_string (state->token, - GST_RTSP_MEDIA_FACTORY_ROLE))) - goto done; - if (!(perms = gst_rtsp_media_factory_get_permissions (state->factory))) - goto done; - - if (g_str_equal (check, "auth.check.media.factory.access")) - res = - gst_rtsp_permissions_is_allowed (perms, role, - GST_RTSP_MEDIA_FACTORY_PERM_ACCESS); - else if (g_str_equal (check, "auth.check.media.factory.construct")) - res = - gst_rtsp_permissions_is_allowed (perms, role, - GST_RTSP_MEDIA_FACTORY_PERM_CONSTRUCT); + res = check_factory (auth, state, check); } -done: return res; } diff --git a/gst/rtsp-server/rtsp-auth.h b/gst/rtsp-server/rtsp-auth.h index 29044de..b38d8d2 100644 --- a/gst/rtsp-server/rtsp-auth.h +++ b/gst/rtsp-server/rtsp-auth.h @@ -53,24 +53,20 @@ struct _GstRTSPAuth { /** * GstRTSPAuthClass: - * @setup: called when an unauthorized resource has been accessed and - * authentication needs to be requested to the client. The default - * implementation adds basic authentication to the response. * @authenticate: check the authentication of a client. The default implementation * checks if the authentication in the header matches one of the basic * authentication tokens. This function should set the authgroup field * in the state. * @check: check if a resource can be accessed. this function should - * call validate to authenticate the client when needed. The default - * implementation disallows unauthenticated access to all methods - * except OPTIONS. + * call authenticate to authenticate the client when needed. The method + * should also construct and send an appropriate response message on + * error. * * The authentication class. */ struct _GstRTSPAuthClass { GObjectClass parent_class; - gboolean (*setup) (GstRTSPAuth *auth, GstRTSPClientState *state); gboolean (*authenticate) (GstRTSPAuth *auth, GstRTSPClientState *state); gboolean (*check) (GstRTSPAuth *auth, GstRTSPClientState *state, const gchar *check); @@ -87,8 +83,6 @@ void gst_rtsp_auth_add_basic (GstRTSPAuth *auth, const gc GstRTSPToken *token); void gst_rtsp_auth_remove_basic (GstRTSPAuth *auth, const gchar * basic); -gboolean gst_rtsp_auth_setup (GstRTSPAuth *auth, GstRTSPClientState *state); - gboolean gst_rtsp_auth_check (const gchar *check); diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c index 529d7cc..1424032 100644 --- a/gst/rtsp-server/rtsp-client.c +++ b/gst/rtsp-server/rtsp-client.c @@ -470,22 +470,6 @@ send_generic_response (GstRTSPClient * client, GstRTSPStatusCode code, send_message (client, NULL, state->response, FALSE); } -static void -handle_unauthorized_request (GstRTSPClient * client, GstRTSPAuth * auth, - GstRTSPClientState * state) -{ - gst_rtsp_message_init_response (state->response, GST_RTSP_STS_UNAUTHORIZED, - gst_rtsp_status_as_text (GST_RTSP_STS_UNAUTHORIZED), state->request); - - if (auth) { - /* and let the authentication manager setup the auth tokens */ - gst_rtsp_auth_setup (auth, state); - } - - send_message (client, state->session, state->response, FALSE); -} - - static gboolean paths_are_equal (const gchar * path1, const gchar * path2, gint len2) { @@ -599,13 +583,11 @@ no_factory: no_factory_access: { GST_ERROR ("client %p: not authorized to see factory uri %s", client, path); - send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state); return NULL; } not_authorized: { GST_ERROR ("client %p: not authorized for factory uri %s", client, path); - handle_unauthorized_request (client, priv->auth, state); return NULL; } no_media: @@ -2030,7 +2012,6 @@ session_not_found: not_authorized: { GST_ERROR ("client %p: not allowed", client); - handle_unauthorized_request (client, priv->auth, &state); goto done; } not_implemented: