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:
Wim Taymans 2013-07-09 16:04:35 +02:00
parent c9d6455ad3
commit d7dec33328
3 changed files with 142 additions and 84 deletions

View file

@ -46,12 +46,11 @@ 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, GstRTSPClient * client,
GstRTSPClientState * state);
static gboolean default_setup (GstRTSPAuth * auth, GstRTSPClientState * state);
static gboolean default_authenticate (GstRTSPAuth * auth,
GstRTSPClient * client, GstRTSPClientState * state);
static gboolean default_check (GstRTSPAuth * auth, GstRTSPClient * client,
GQuark hint, GstRTSPClientState * state);
GstRTSPClientState * state);
static gboolean default_check (GstRTSPAuth * auth, GstRTSPClientState * state,
const gchar * check);
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
default_setup (GstRTSPAuth * auth, GstRTSPClient * client,
GstRTSPClientState * state)
default_setup (GstRTSPAuth * auth, GstRTSPClientState * state)
{
if (state->response == NULL)
return FALSE;
@ -221,14 +219,12 @@ default_setup (GstRTSPAuth * auth, GstRTSPClient * client,
* Returns: FALSE if something is wrong.
*/
gboolean
gst_rtsp_auth_setup (GstRTSPAuth * auth, GstRTSPClient * client,
GstRTSPClientState * state)
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 (GST_IS_RTSP_CLIENT (client), FALSE);
g_return_val_if_fail (state != NULL, FALSE);
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");
if (klass->setup)
result = klass->setup (auth, client, state);
result = klass->setup (auth, state);
return result;
}
static gboolean
default_authenticate (GstRTSPAuth * auth, GstRTSPClient * client,
GstRTSPClientState * state)
default_authenticate (GstRTSPAuth * auth, GstRTSPClientState * state)
{
GstRTSPAuthPrivate *priv = auth->priv;
GstRTSPResult res;
@ -282,41 +277,25 @@ no_auth:
}
static gboolean
default_check (GstRTSPAuth * auth, GstRTSPClient * client,
GstRTSPAuthCheck check, GstRTSPClientState * state)
ensure_authenticated (GstRTSPAuth * auth, GstRTSPClientState * state)
{
GstRTSPAuthPrivate *priv = auth->priv;
GstRTSPAuthClass *klass;
gboolean need_authorized = FALSE;
gboolean res = FALSE;
klass = GST_RTSP_AUTH_GET_CLASS (auth);
switch (check) {
case GST_RTSP_AUTH_CHECK_URL:
if ((state->method & priv->methods) != 0)
need_authorized = TRUE;
else
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;
}
/* we need a token to check */
if (state->token == NULL) {
if (klass->authenticate) {
if (!klass->authenticate (auth, 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:
{
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:
* @auth: a #GstRTSPAuth
* @client: the client
* @check: the item to check
* @state: client state
*
* Check if @client with state is authorized to perform @check in the
* current @state.
* Check if @check is allowed in the current context.
*
* Returns: FALSE if check failed.
*/
gboolean
gst_rtsp_auth_check (GstRTSPAuth * auth, GstRTSPClient * client,
GstRTSPAuthCheck check, GstRTSPClientState * state)
gst_rtsp_auth_check (const gchar * check)
{
gboolean result = FALSE;
GstRTSPAuthClass *klass;
GstRTSPClientState *state;
GstRTSPAuth *auth;
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 (check != 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);
GST_DEBUG_OBJECT (auth, "check auth");
if (klass->check)
result = klass->check (auth, client, check, state);
result = klass->check (auth, state, check);
return result;
/* ERRORS */
no_state:
{
GST_ERROR ("no clientstate found");
return FALSE;
}
}
/**

View file

@ -40,18 +40,6 @@ G_BEGIN_DECLS
#define GST_RTSP_AUTH_CAST(obj) ((GstRTSPAuth*)(obj))
#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:
*
@ -82,12 +70,10 @@ struct _GstRTSPAuth {
struct _GstRTSPAuthClass {
GObjectClass parent_class;
gboolean (*setup) (GstRTSPAuth *auth, GstRTSPClient * client,
GstRTSPClientState *state);
gboolean (*authenticate) (GstRTSPAuth *auth, GstRTSPClient * client,
GstRTSPClientState *state);
gboolean (*check) (GstRTSPAuth *auth, GstRTSPClient * client,
GstRTSPAuthCheck check, GstRTSPClientState *state);
gboolean (*setup) (GstRTSPAuth *auth, GstRTSPClientState *state);
gboolean (*authenticate) (GstRTSPAuth *auth, GstRTSPClientState *state);
gboolean (*check) (GstRTSPAuth *auth, GstRTSPClientState *state,
const gchar *check);
};
GType gst_rtsp_auth_get_type (void);
@ -98,15 +84,60 @@ 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, GstRTSPClient * client,
GstRTSPClientState *state);
gboolean gst_rtsp_auth_setup (GstRTSPAuth *auth, GstRTSPClientState *state);
gboolean gst_rtsp_auth_check (const gchar *check);
gboolean gst_rtsp_auth_check (GstRTSPAuth *auth, GstRTSPClient * client,
GstRTSPAuthCheck check, GstRTSPClientState *state);
/* helpers */
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
#endif /* __GST_RTSP_AUTH_H__ */

View file

@ -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, client, state);
gst_rtsp_auth_setup (auth, state);
}
send_message (client, state->session, state->response, FALSE);
@ -502,8 +502,10 @@ find_media (GstRTSPClient * client, GstRTSPClientState * state, gint * matched)
state->factory = factory;
if (!gst_rtsp_auth_check (priv->auth, client, GST_RTSP_AUTH_CHECK_FACTORY,
state))
if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS))
goto no_factory_access;
if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT))
goto not_authorized;
if (matched)
@ -563,9 +565,15 @@ no_factory:
send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
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:
{
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);
return NULL;
}
@ -1858,13 +1866,8 @@ handle_request (GstRTSPClient * client, GstRTSPMessage * request)
state.uri = uri;
state.session = session;
if (priv->auth) {
if (!gst_rtsp_auth_check (priv->auth, client, GST_RTSP_AUTH_CHECK_URL,
&state))
goto not_authorized;
state.auth = priv->auth;
}
if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_URL))
goto not_authorized;
/* now see what is asked and dispatch to a dedicated handler */
switch (method) {