From f01aded72c38f0e18bc7ff67dee800e380251c8e Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Mon, 11 Feb 2013 22:36:58 +0100 Subject: io: Implement strict load policy Allow any file to load from data:, and any resource to load from other resources. Only allow file: to load other file: URIs from below the path of the base file. Any other loads are denied. Bug #691708. --- rsvg-base.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 8 deletions(-) (limited to 'rsvg-base.c') diff --git a/rsvg-base.c b/rsvg-base.c index 1f88479f..9d7c1ea9 100644 --- a/rsvg-base.c +++ b/rsvg-base.c @@ -25,6 +25,7 @@ */ #include "config.h" +#define _GNU_SOURCE 1 #include "rsvg.h" #include "rsvg-private.h" @@ -1002,6 +1003,7 @@ void rsvg_handle_set_base_uri (RsvgHandle * handle, const char *base_uri) { gchar *uri; + GFile *file; g_return_if_fail (handle != NULL); @@ -1013,11 +1015,10 @@ rsvg_handle_set_base_uri (RsvgHandle * handle, const char *base_uri) else uri = rsvg_get_base_uri_from_filename (base_uri); - if (uri) { - if (handle->priv->base_uri) - g_free (handle->priv->base_uri); - handle->priv->base_uri = uri; - } + file = g_file_new_for_uri (uri ? uri : "data:"); + rsvg_handle_set_base_gfile (handle, file); + g_object_unref (file); + g_free (uri); } /** @@ -2149,12 +2150,84 @@ _rsvg_handle_allow_load (RsvgHandle *handle, const char *uri, GError **error) { - RsvgLoadPolicy policy = handle->priv->load_policy; + RsvgHandlePrivate *priv = handle->priv; + GFile *base; + char *path, *dir; + char *scheme = NULL, *cpath = NULL, *cdir = NULL; - if (policy == RSVG_LOAD_POLICY_ALL_PERMISSIVE) - return TRUE; + g_assert (handle->priv->load_policy == RSVG_LOAD_POLICY_STRICT); + + scheme = g_uri_parse_scheme (uri); + + /* Not a valid URI */ + if (scheme == NULL) + goto deny; + + /* Allow loads of data: from any location */ + if (g_str_equal (scheme, "data")) + goto allow; + + /* No base to compare to? */ + if (priv->base_gfile == NULL) + goto deny; + + /* Deny loads from differing URI schemes */ + if (!g_file_has_uri_scheme (priv->base_gfile, scheme)) + goto deny; + + /* resource: is allowed to load anything from other resources */ + if (g_str_equal (scheme, "resource")) + goto allow; + + /* Non-file: isn't allowed to load anything */ + if (!g_str_equal (scheme, "file")) + goto deny; + + base = g_file_get_parent (priv->base_gfile); + if (base == NULL) + goto deny; + dir = g_file_get_path (base); + g_object_unref (base); + + /* FIXME portability */ + cdir = canonicalize_file_name (dir); + g_free (dir); + if (cdir == NULL) + goto deny; + + path = g_filename_from_uri (uri, NULL, NULL); + if (path == NULL) + goto deny; + + /* FIXME portability */ + cpath = canonicalize_file_name (path); + g_free (path); + + if (cpath == NULL) + goto deny; + + /* Now check that @cpath is below @cdir */ + if (!g_str_has_prefix (cpath, cdir) || + cpath[strlen (cdir)] != G_DIR_SEPARATOR) + goto deny; + + /* Allow load! */ + + allow: + g_free (scheme); + free (cpath); + free (cdir); return TRUE; + + deny: + g_free (scheme); + free (cpath); + free (cdir); + + g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, + "File may not link to URI \"%s\"", uri); + return FALSE; } static char * -- cgit v1.2.1