summaryrefslogtreecommitdiff
path: root/rsvg-base.c
diff options
context:
space:
mode:
authorChristian Persch <chpe@gnome.org>2013-02-11 22:36:58 +0100
committerChristian Persch <chpe@gnome.org>2013-03-10 12:50:06 +0100
commitf01aded72c38f0e18bc7ff67dee800e380251c8e (patch)
tree86d1c5c8be0cd6884170d6e3afcabdd6d82aa98d /rsvg-base.c
parentd83e426fff3f6d0fa6042d0930fb70357db24125 (diff)
downloadlibrsvg-f01aded72c38f0e18bc7ff67dee800e380251c8e.tar.gz
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.
Diffstat (limited to 'rsvg-base.c')
-rw-r--r--rsvg-base.c89
1 files changed, 81 insertions, 8 deletions
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 *