mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
auth: simplify auth checks
Remove client from methods, it's now in the state Perform the check specified by the string, use the information from the thread local context.
This commit is contained in:
parent
c9d6455ad3
commit
d7dec33328
3 changed files with 142 additions and 84 deletions
|
@ -46,12 +46,11 @@ static void gst_rtsp_auth_set_property (GObject * object, guint propid,
|
||||||
const GValue * value, GParamSpec * pspec);
|
const GValue * value, GParamSpec * pspec);
|
||||||
static void gst_rtsp_auth_finalize (GObject * obj);
|
static void gst_rtsp_auth_finalize (GObject * obj);
|
||||||
|
|
||||||
static gboolean default_setup (GstRTSPAuth * auth, GstRTSPClient * client,
|
static gboolean default_setup (GstRTSPAuth * auth, GstRTSPClientState * state);
|
||||||
GstRTSPClientState * state);
|
|
||||||
static gboolean default_authenticate (GstRTSPAuth * auth,
|
static gboolean default_authenticate (GstRTSPAuth * auth,
|
||||||
GstRTSPClient * client, GstRTSPClientState * state);
|
GstRTSPClientState * state);
|
||||||
static gboolean default_check (GstRTSPAuth * auth, GstRTSPClient * client,
|
static gboolean default_check (GstRTSPAuth * auth, GstRTSPClientState * state,
|
||||||
GQuark hint, GstRTSPClientState * state);
|
const gchar * check);
|
||||||
|
|
||||||
G_DEFINE_TYPE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT);
|
G_DEFINE_TYPE (GstRTSPAuth, gst_rtsp_auth, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
@ -197,8 +196,7 @@ gst_rtsp_auth_remove_basic (GstRTSPAuth * auth, const gchar * basic)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
default_setup (GstRTSPAuth * auth, GstRTSPClient * client,
|
default_setup (GstRTSPAuth * auth, GstRTSPClientState * state)
|
||||||
GstRTSPClientState * state)
|
|
||||||
{
|
{
|
||||||
if (state->response == NULL)
|
if (state->response == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -221,14 +219,12 @@ default_setup (GstRTSPAuth * auth, GstRTSPClient * client,
|
||||||
* Returns: FALSE if something is wrong.
|
* Returns: FALSE if something is wrong.
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_rtsp_auth_setup (GstRTSPAuth * auth, GstRTSPClient * client,
|
gst_rtsp_auth_setup (GstRTSPAuth * auth, GstRTSPClientState * state)
|
||||||
GstRTSPClientState * state)
|
|
||||||
{
|
{
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
GstRTSPAuthClass *klass;
|
GstRTSPAuthClass *klass;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), FALSE);
|
g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), FALSE);
|
||||||
g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), FALSE);
|
|
||||||
g_return_val_if_fail (state != NULL, FALSE);
|
g_return_val_if_fail (state != NULL, FALSE);
|
||||||
|
|
||||||
klass = GST_RTSP_AUTH_GET_CLASS (auth);
|
klass = GST_RTSP_AUTH_GET_CLASS (auth);
|
||||||
|
@ -236,14 +232,13 @@ gst_rtsp_auth_setup (GstRTSPAuth * auth, GstRTSPClient * client,
|
||||||
GST_DEBUG_OBJECT (auth, "setup auth");
|
GST_DEBUG_OBJECT (auth, "setup auth");
|
||||||
|
|
||||||
if (klass->setup)
|
if (klass->setup)
|
||||||
result = klass->setup (auth, client, state);
|
result = klass->setup (auth, state);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
default_authenticate (GstRTSPAuth * auth, GstRTSPClient * client,
|
default_authenticate (GstRTSPAuth * auth, GstRTSPClientState * state)
|
||||||
GstRTSPClientState * state)
|
|
||||||
{
|
{
|
||||||
GstRTSPAuthPrivate *priv = auth->priv;
|
GstRTSPAuthPrivate *priv = auth->priv;
|
||||||
GstRTSPResult res;
|
GstRTSPResult res;
|
||||||
|
@ -282,41 +277,25 @@ no_auth:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
default_check (GstRTSPAuth * auth, GstRTSPClient * client,
|
ensure_authenticated (GstRTSPAuth * auth, GstRTSPClientState * state)
|
||||||
GstRTSPAuthCheck check, GstRTSPClientState * state)
|
|
||||||
{
|
{
|
||||||
GstRTSPAuthPrivate *priv = auth->priv;
|
|
||||||
GstRTSPAuthClass *klass;
|
GstRTSPAuthClass *klass;
|
||||||
gboolean need_authorized = FALSE;
|
|
||||||
gboolean res = FALSE;
|
|
||||||
|
|
||||||
klass = GST_RTSP_AUTH_GET_CLASS (auth);
|
klass = GST_RTSP_AUTH_GET_CLASS (auth);
|
||||||
|
|
||||||
switch (check) {
|
/* we need a token to check */
|
||||||
case GST_RTSP_AUTH_CHECK_URL:
|
if (state->token == NULL) {
|
||||||
if ((state->method & priv->methods) != 0)
|
if (klass->authenticate) {
|
||||||
need_authorized = TRUE;
|
if (!klass->authenticate (auth, state))
|
||||||
else
|
goto authenticate_failed;
|
||||||
res = TRUE;
|
|
||||||
break;
|
|
||||||
case GST_RTSP_AUTH_CHECK_FACTORY:
|
|
||||||
res = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (need_authorized) {
|
|
||||||
/* we need a token to check */
|
|
||||||
if (state->token == NULL) {
|
|
||||||
if (klass->authenticate) {
|
|
||||||
if (!klass->authenticate (auth, client, state))
|
|
||||||
goto authenticate_failed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (state->token == NULL)
|
|
||||||
goto no_auth;
|
|
||||||
}
|
}
|
||||||
return res;
|
if (state->token == NULL)
|
||||||
|
goto no_auth;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
authenticate_failed:
|
authenticate_failed:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (auth, "authenticate failed");
|
GST_DEBUG_OBJECT (auth, "authenticate failed");
|
||||||
|
@ -329,37 +308,82 @@ no_auth:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
default_check (GstRTSPAuth * auth, GstRTSPClientState * state,
|
||||||
|
const gchar * check)
|
||||||
|
{
|
||||||
|
GstRTSPAuthPrivate *priv = auth->priv;
|
||||||
|
gboolean res = FALSE;
|
||||||
|
|
||||||
|
if (g_str_equal (check, GST_RTSP_AUTH_CHECK_URL)) {
|
||||||
|
if ((state->method & priv->methods) != 0)
|
||||||
|
res = ensure_authenticated (auth, state);
|
||||||
|
else
|
||||||
|
res = TRUE;
|
||||||
|
} else if (g_str_has_prefix (check, "auth.check.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);
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_rtsp_auth_check:
|
* gst_rtsp_auth_check:
|
||||||
* @auth: a #GstRTSPAuth
|
|
||||||
* @client: the client
|
|
||||||
* @check: the item to check
|
* @check: the item to check
|
||||||
* @state: client state
|
|
||||||
*
|
*
|
||||||
* Check if @client with state is authorized to perform @check in the
|
* Check if @check is allowed in the current context.
|
||||||
* current @state.
|
|
||||||
*
|
*
|
||||||
* Returns: FALSE if check failed.
|
* Returns: FALSE if check failed.
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_rtsp_auth_check (GstRTSPAuth * auth, GstRTSPClient * client,
|
gst_rtsp_auth_check (const gchar * check)
|
||||||
GstRTSPAuthCheck check, GstRTSPClientState * state)
|
|
||||||
{
|
{
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
GstRTSPAuthClass *klass;
|
GstRTSPAuthClass *klass;
|
||||||
|
GstRTSPClientState *state;
|
||||||
|
GstRTSPAuth *auth;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), FALSE);
|
g_return_val_if_fail (check != NULL, FALSE);
|
||||||
g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), FALSE);
|
|
||||||
g_return_val_if_fail (state != NULL, FALSE);
|
if (!(state = gst_rtsp_client_state_get_current ()))
|
||||||
|
goto no_state;
|
||||||
|
|
||||||
|
/* no auth, we don't need to check */
|
||||||
|
if (!(auth = state->auth))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
klass = GST_RTSP_AUTH_GET_CLASS (auth);
|
klass = GST_RTSP_AUTH_GET_CLASS (auth);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (auth, "check auth");
|
GST_DEBUG_OBJECT (auth, "check auth");
|
||||||
|
|
||||||
if (klass->check)
|
if (klass->check)
|
||||||
result = klass->check (auth, client, check, state);
|
result = klass->check (auth, state, check);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_state:
|
||||||
|
{
|
||||||
|
GST_ERROR ("no clientstate found");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -40,18 +40,6 @@ G_BEGIN_DECLS
|
||||||
#define GST_RTSP_AUTH_CAST(obj) ((GstRTSPAuth*)(obj))
|
#define GST_RTSP_AUTH_CAST(obj) ((GstRTSPAuth*)(obj))
|
||||||
#define GST_RTSP_AUTH_CLASS_CAST(klass) ((GstRTSPAuthClass*)(klass))
|
#define GST_RTSP_AUTH_CLASS_CAST(klass) ((GstRTSPAuthClass*)(klass))
|
||||||
|
|
||||||
/**
|
|
||||||
* GstRTSPAuthCheck:
|
|
||||||
* @GST_RTSP_AUTH_CHECK_URL: Check url and method
|
|
||||||
* @GST_RTSP_AUTH_CHECK_FACTORY: Check access to factory
|
|
||||||
*
|
|
||||||
* Different authorization checks
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
GST_RTSP_AUTH_CHECK_URL,
|
|
||||||
GST_RTSP_AUTH_CHECK_FACTORY,
|
|
||||||
} GstRTSPAuthCheck;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstRTSPAuth:
|
* GstRTSPAuth:
|
||||||
*
|
*
|
||||||
|
@ -82,12 +70,10 @@ struct _GstRTSPAuth {
|
||||||
struct _GstRTSPAuthClass {
|
struct _GstRTSPAuthClass {
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
gboolean (*setup) (GstRTSPAuth *auth, GstRTSPClient * client,
|
gboolean (*setup) (GstRTSPAuth *auth, GstRTSPClientState *state);
|
||||||
GstRTSPClientState *state);
|
gboolean (*authenticate) (GstRTSPAuth *auth, GstRTSPClientState *state);
|
||||||
gboolean (*authenticate) (GstRTSPAuth *auth, GstRTSPClient * client,
|
gboolean (*check) (GstRTSPAuth *auth, GstRTSPClientState *state,
|
||||||
GstRTSPClientState *state);
|
const gchar *check);
|
||||||
gboolean (*check) (GstRTSPAuth *auth, GstRTSPClient * client,
|
|
||||||
GstRTSPAuthCheck check, GstRTSPClientState *state);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_rtsp_auth_get_type (void);
|
GType gst_rtsp_auth_get_type (void);
|
||||||
|
@ -98,15 +84,60 @@ void gst_rtsp_auth_add_basic (GstRTSPAuth *auth, const gc
|
||||||
GstRTSPToken *token);
|
GstRTSPToken *token);
|
||||||
void gst_rtsp_auth_remove_basic (GstRTSPAuth *auth, const gchar * basic);
|
void gst_rtsp_auth_remove_basic (GstRTSPAuth *auth, const gchar * basic);
|
||||||
|
|
||||||
gboolean gst_rtsp_auth_setup (GstRTSPAuth *auth, GstRTSPClient * client,
|
gboolean gst_rtsp_auth_setup (GstRTSPAuth *auth, GstRTSPClientState *state);
|
||||||
GstRTSPClientState *state);
|
|
||||||
|
gboolean gst_rtsp_auth_check (const gchar *check);
|
||||||
|
|
||||||
gboolean gst_rtsp_auth_check (GstRTSPAuth *auth, GstRTSPClient * client,
|
|
||||||
GstRTSPAuthCheck check, GstRTSPClientState *state);
|
|
||||||
|
|
||||||
/* helpers */
|
/* helpers */
|
||||||
gchar * gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass);
|
gchar * gst_rtsp_auth_make_basic (const gchar * user, const gchar * pass);
|
||||||
|
|
||||||
|
/* checks */
|
||||||
|
/**
|
||||||
|
* GST_RTSP_AUTH_CHECK_URL:
|
||||||
|
*
|
||||||
|
* Check the URL and methods
|
||||||
|
*/
|
||||||
|
#define GST_RTSP_AUTH_CHECK_URL "auth.check.url"
|
||||||
|
/**
|
||||||
|
* GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS:
|
||||||
|
*
|
||||||
|
* Check if access is allowed to a factory
|
||||||
|
*/
|
||||||
|
#define GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS "auth.check.media.factory.access"
|
||||||
|
/**
|
||||||
|
* GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT:
|
||||||
|
*
|
||||||
|
* Check if media can be constructed from a media factory
|
||||||
|
*/
|
||||||
|
#define GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT "auth.check.media.factory.construct"
|
||||||
|
|
||||||
|
|
||||||
|
/* tokens */
|
||||||
|
/**
|
||||||
|
* GST_RTSP_MEDIA_FACTORY_ROLE:
|
||||||
|
*
|
||||||
|
* G_TYPE_STRING, the role to use when dealing with media factories
|
||||||
|
*/
|
||||||
|
#define GST_RTSP_MEDIA_FACTORY_ROLE "media.factory.role"
|
||||||
|
|
||||||
|
/* permissions */
|
||||||
|
/**
|
||||||
|
* GST_RTSP_MEDIA_FACTORY_PERM_ACCESS:
|
||||||
|
*
|
||||||
|
* G_TYPE_BOOLEAN, %TRUE if the media can be accessed, %FALSE will
|
||||||
|
* return a 404 Not Found error when trying to access the media.
|
||||||
|
*/
|
||||||
|
#define GST_RTSP_MEDIA_FACTORY_PERM_ACCESS "media.factory.access"
|
||||||
|
/**
|
||||||
|
* GST_RTSP_MEDIA_FACTORY_PERM_CONSTRUCT:
|
||||||
|
*
|
||||||
|
* G_TYPE_BOOLEAN, %TRUE if the media can be constructed, %FALSE will
|
||||||
|
* return a 404 Not Found error when trying to access the media.
|
||||||
|
*/
|
||||||
|
#define GST_RTSP_MEDIA_FACTORY_PERM_CONSTRUCT "media.factory.construct"
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_RTSP_AUTH_H__ */
|
#endif /* __GST_RTSP_AUTH_H__ */
|
||||||
|
|
|
@ -456,7 +456,7 @@ handle_unauthorized_request (GstRTSPClient * client, GstRTSPAuth * auth,
|
||||||
|
|
||||||
if (auth) {
|
if (auth) {
|
||||||
/* and let the authentication manager setup the auth tokens */
|
/* and let the authentication manager setup the auth tokens */
|
||||||
gst_rtsp_auth_setup (auth, client, state);
|
gst_rtsp_auth_setup (auth, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
send_message (client, state->session, state->response, FALSE);
|
send_message (client, state->session, state->response, FALSE);
|
||||||
|
@ -502,8 +502,10 @@ find_media (GstRTSPClient * client, GstRTSPClientState * state, gint * matched)
|
||||||
|
|
||||||
state->factory = factory;
|
state->factory = factory;
|
||||||
|
|
||||||
if (!gst_rtsp_auth_check (priv->auth, client, GST_RTSP_AUTH_CHECK_FACTORY,
|
if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS))
|
||||||
state))
|
goto no_factory_access;
|
||||||
|
|
||||||
|
if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT))
|
||||||
goto not_authorized;
|
goto not_authorized;
|
||||||
|
|
||||||
if (matched)
|
if (matched)
|
||||||
|
@ -563,9 +565,15 @@ no_factory:
|
||||||
send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
|
send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
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:
|
not_authorized:
|
||||||
{
|
{
|
||||||
GST_ERROR ("client %p: not authorized for factory %p", client, factory);
|
GST_ERROR ("client %p: not authorized for factory uri %s", client, path);
|
||||||
handle_unauthorized_request (client, priv->auth, state);
|
handle_unauthorized_request (client, priv->auth, state);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1858,13 +1866,8 @@ handle_request (GstRTSPClient * client, GstRTSPMessage * request)
|
||||||
state.uri = uri;
|
state.uri = uri;
|
||||||
state.session = session;
|
state.session = session;
|
||||||
|
|
||||||
if (priv->auth) {
|
if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_URL))
|
||||||
if (!gst_rtsp_auth_check (priv->auth, client, GST_RTSP_AUTH_CHECK_URL,
|
goto not_authorized;
|
||||||
&state))
|
|
||||||
goto not_authorized;
|
|
||||||
|
|
||||||
state.auth = priv->auth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now see what is asked and dispatch to a dedicated handler */
|
/* now see what is asked and dispatch to a dedicated handler */
|
||||||
switch (method) {
|
switch (method) {
|
||||||
|
|
Loading…
Reference in a new issue