diff options
Diffstat (limited to 'gst/rtsp-server/rtsp-auth.c')
-rw-r--r-- | gst/rtsp-server/rtsp-auth.c | 163 |
1 files changed, 111 insertions, 52 deletions
diff --git a/gst/rtsp-server/rtsp-auth.c b/gst/rtsp-server/rtsp-auth.c index da575ee..7264128 100644 --- a/gst/rtsp-server/rtsp-auth.c +++ b/gst/rtsp-server/rtsp-auth.c @@ -31,7 +31,7 @@ * The RTSP server will call gst_rtsp_auth_check() with a string describing the * check to perform. The possible checks are prefixed with * #GST_RTSP_AUTH_CHECK_*. Depending on the check, the default implementation - * will use the current #GstRTSPToken, #GstRTSPClientState and + * will use the current #GstRTSPToken, #GstRTSPContext and * #GstRTSPPermissions on the object to check if an operation is allowed. * * The default #GstRTSPAuth object has support for basic authentication. With @@ -60,6 +60,7 @@ struct _GstRTSPAuthPrivate /* the TLS certificate */ GTlsCertificate *certificate; GHashTable *basic; /* protected by lock */ + GstRTSPToken *default_token; GstRTSPMethod methods; }; @@ -78,9 +79,8 @@ 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_authenticate (GstRTSPAuth * auth, - GstRTSPClientState * state); -static gboolean default_check (GstRTSPAuth * auth, GstRTSPClientState * state, +static gboolean default_authenticate (GstRTSPAuth * auth, GstRTSPContext * ctx); +static gboolean default_check (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check); G_DEFINE_TYPE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT); @@ -230,6 +230,63 @@ gst_rtsp_auth_get_tls_certificate (GstRTSPAuth * auth) return result; } +/** + * gst_rtsp_auth_set_default_token: + * @auth: a #GstRTSPAuth + * @token: (allow none): a #GstRTSPToken + * + * Set the default #GstRTSPToken to @token in @auth. The default token will + * be used for unauthenticated users. + */ +void +gst_rtsp_auth_set_default_token (GstRTSPAuth * auth, GstRTSPToken * token) +{ + GstRTSPAuthPrivate *priv; + GstRTSPToken *old; + + g_return_if_fail (GST_IS_RTSP_AUTH (auth)); + + priv = auth->priv; + + if (token) + gst_rtsp_token_ref (token); + + g_mutex_lock (&priv->lock); + old = priv->default_token; + priv->default_token = token; + g_mutex_unlock (&priv->lock); + + if (old) + gst_rtsp_token_unref (old); +} + +/** + * gst_rtsp_auth_get_default_token: + * @auth: a #GstRTSPAuth + * + * Get the default token for @auth. This token will be used for unauthorized + * users. + * + * Returns: (transfer full): the #GstRTSPToken of @auth. gst_rtsp_token_unref() after + * usage. + */ +GstRTSPToken * +gst_rtsp_auth_get_default_token (GstRTSPAuth * auth) +{ + GstRTSPAuthPrivate *priv; + GstRTSPToken *result; + + g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL); + + priv = auth->priv; + + g_mutex_lock (&priv->lock); + if ((result = priv->default_token)) + gst_rtsp_token_ref (result); + g_mutex_unlock (&priv->lock); + + return result; +} /** * gst_rtsp_auth_add_basic: @@ -282,7 +339,7 @@ gst_rtsp_auth_remove_basic (GstRTSPAuth * auth, const gchar * basic) } static gboolean -default_authenticate (GstRTSPAuth * auth, GstRTSPClientState * state) +default_authenticate (GstRTSPAuth * auth, GstRTSPContext * ctx) { GstRTSPAuthPrivate *priv = auth->priv; GstRTSPResult res; @@ -290,8 +347,14 @@ default_authenticate (GstRTSPAuth * auth, GstRTSPClientState * state) GST_DEBUG_OBJECT (auth, "authenticate"); + g_mutex_lock (&priv->lock); + /* FIXME, need to ref but we have no way to unref when the ctx is + * popped */ + ctx->token = priv->default_token; + g_mutex_unlock (&priv->lock); + res = - gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_AUTHORIZATION, + gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_AUTHORIZATION, &authorization, 0); if (res < 0) goto no_auth; @@ -304,7 +367,7 @@ default_authenticate (GstRTSPAuth * auth, GstRTSPClientState * state) g_mutex_lock (&priv->lock); if ((token = g_hash_table_lookup (priv->basic, &authorization[6]))) { GST_DEBUG_OBJECT (auth, "setting token %p", token); - state->token = token; + ctx->token = token; } g_mutex_unlock (&priv->lock); } else if (g_ascii_strncasecmp (authorization, "digest ", 7) == 0) { @@ -321,35 +384,34 @@ no_auth: } static void -send_response (GstRTSPAuth * auth, GstRTSPStatusCode code, - GstRTSPClientState * state) +send_response (GstRTSPAuth * auth, GstRTSPStatusCode code, GstRTSPContext * ctx) { - gst_rtsp_message_init_response (state->response, code, - gst_rtsp_status_as_text (code), state->request); + gst_rtsp_message_init_response (ctx->response, code, + gst_rtsp_status_as_text (code), ctx->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, + gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_WWW_AUTHENTICATE, "Basic realm=\"GStreamer RTSP Server\""); } - gst_rtsp_client_send_message (state->client, state->session, state->response); + gst_rtsp_client_send_message (ctx->client, ctx->session, ctx->response); } static gboolean -ensure_authenticated (GstRTSPAuth * auth, GstRTSPClientState * state) +ensure_authenticated (GstRTSPAuth * auth, GstRTSPContext * ctx) { GstRTSPAuthClass *klass; klass = GST_RTSP_AUTH_GET_CLASS (auth); /* we need a token to check */ - if (state->token == NULL) { + if (ctx->token == NULL) { if (klass->authenticate) { - if (!klass->authenticate (auth, state)) + if (!klass->authenticate (auth, ctx)) goto authenticate_failed; } } - if (state->token == NULL) + if (ctx->token == NULL) goto no_auth; return TRUE; @@ -358,21 +420,20 @@ ensure_authenticated (GstRTSPAuth * auth, GstRTSPClientState * state) authenticate_failed: { GST_DEBUG_OBJECT (auth, "authenticate failed"); - send_response (auth, GST_RTSP_STS_UNAUTHORIZED, state); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx); return FALSE; } no_auth: { GST_DEBUG_OBJECT (auth, "no authorization token found"); - send_response (auth, GST_RTSP_STS_UNAUTHORIZED, state); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx); return FALSE; } } /* new connection */ static gboolean -check_connect (GstRTSPAuth * auth, GstRTSPClientState * state, - const gchar * check) +check_connect (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check) { GstRTSPAuthPrivate *priv = auth->priv; @@ -380,7 +441,7 @@ check_connect (GstRTSPAuth * auth, GstRTSPClientState * state, GTlsConnection *tls; /* configure the connection */ - tls = gst_rtsp_connection_get_tls (state->conn, NULL); + tls = gst_rtsp_connection_get_tls (ctx->conn, NULL); g_tls_connection_set_certificate (tls, priv->certificate); } return TRUE; @@ -388,12 +449,12 @@ check_connect (GstRTSPAuth * auth, GstRTSPClientState * state, /* check url and methods */ static gboolean -check_url (GstRTSPAuth * auth, GstRTSPClientState * state, const gchar * check) +check_url (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check) { GstRTSPAuthPrivate *priv = auth->priv; - if ((state->method & priv->methods) != 0) - if (!ensure_authenticated (auth, state)) + if ((ctx->method & priv->methods) != 0) + if (!ensure_authenticated (auth, ctx)) goto not_authenticated; return TRUE; @@ -407,26 +468,25 @@ not_authenticated: /* check access to media factory */ static gboolean -check_factory (GstRTSPAuth * auth, GstRTSPClientState * state, - const gchar * check) +check_factory (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check) { const gchar *role; GstRTSPPermissions *perms; - if (!ensure_authenticated (auth, state)) + if (!ensure_authenticated (auth, ctx)) return FALSE; - if (!(role = gst_rtsp_token_get_string (state->token, + if (!(role = gst_rtsp_token_get_string (ctx->token, GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE))) goto no_media_role; - if (!(perms = gst_rtsp_media_factory_get_permissions (state->factory))) + if (!(perms = gst_rtsp_media_factory_get_permissions (ctx->factory))) goto no_permissions; - if (g_str_equal (check, "auth.check.media.factory.access")) { + if (g_str_equal (check, GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS)) { if (!gst_rtsp_permissions_is_allowed (perms, role, GST_RTSP_PERM_MEDIA_FACTORY_ACCESS)) goto no_access; - } else if (g_str_equal (check, "auth.check.media.factory.construct")) { + } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT)) { if (!gst_rtsp_permissions_is_allowed (perms, role, GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT)) goto no_construct; @@ -437,55 +497,54 @@ check_factory (GstRTSPAuth * auth, GstRTSPClientState * state, no_media_role: { GST_DEBUG_OBJECT (auth, "no media factory role found"); - send_response (auth, GST_RTSP_STS_UNAUTHORIZED, state); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx); return FALSE; } no_permissions: { GST_DEBUG_OBJECT (auth, "no permissions on media factory found"); - send_response (auth, GST_RTSP_STS_UNAUTHORIZED, state); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx); return FALSE; } no_access: { GST_DEBUG_OBJECT (auth, "no permissions to access media factory"); - send_response (auth, GST_RTSP_STS_NOT_FOUND, state); + send_response (auth, GST_RTSP_STS_NOT_FOUND, ctx); return FALSE; } no_construct: { GST_DEBUG_OBJECT (auth, "no permissions to construct media factory"); - send_response (auth, GST_RTSP_STS_UNAUTHORIZED, state); + send_response (auth, GST_RTSP_STS_UNAUTHORIZED, ctx); return FALSE; } } static gboolean -check_client_settings (GstRTSPAuth * auth, GstRTSPClientState * state, +check_client_settings (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check) { - if (!ensure_authenticated (auth, state)) + if (!ensure_authenticated (auth, ctx)) return FALSE; - return gst_rtsp_token_is_allowed (state->token, + return gst_rtsp_token_is_allowed (ctx->token, GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS); } static gboolean -default_check (GstRTSPAuth * auth, GstRTSPClientState * state, - const gchar * check) +default_check (GstRTSPAuth * auth, GstRTSPContext * ctx, const gchar * check) { gboolean res = FALSE; /* FIXME, use hastable or so */ if (g_str_equal (check, GST_RTSP_AUTH_CHECK_CONNECT)) { - res = check_connect (auth, state, check); + res = check_connect (auth, ctx, check); } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_URL)) { - res = check_url (auth, state, check); + res = check_url (auth, ctx, check); } else if (g_str_has_prefix (check, "auth.check.media.factory.")) { - res = check_factory (auth, state, check); + res = check_factory (auth, ctx, check); } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS)) { - res = check_client_settings (auth, state, check); + res = check_client_settings (auth, ctx, check); } return res; } @@ -516,16 +575,16 @@ gst_rtsp_auth_check (const gchar * check) { gboolean result = FALSE; GstRTSPAuthClass *klass; - GstRTSPClientState *state; + GstRTSPContext *ctx; GstRTSPAuth *auth; g_return_val_if_fail (check != NULL, FALSE); - if (!(state = gst_rtsp_client_state_get_current ())) - goto no_state; + if (!(ctx = gst_rtsp_context_get_current ())) + goto no_context; /* no auth, we don't need to check */ - if (!(auth = state->auth)) + if (!(auth = ctx->auth)) return no_auth_check (check); klass = GST_RTSP_AUTH_GET_CLASS (auth); @@ -533,14 +592,14 @@ gst_rtsp_auth_check (const gchar * check) GST_DEBUG_OBJECT (auth, "check authorization '%s'", check); if (klass->check) - result = klass->check (auth, state, check); + result = klass->check (auth, ctx, check); return result; /* ERRORS */ -no_state: +no_context: { - GST_ERROR ("no clientstate found"); + GST_ERROR ("no context found"); return FALSE; } } |