diff options
author | Christian Persch <chpe@gnome.org> | 2013-02-11 22:36:58 +0100 |
---|---|---|
committer | Christian Persch <chpe@gnome.org> | 2013-03-10 12:50:06 +0100 |
commit | f01aded72c38f0e18bc7ff67dee800e380251c8e (patch) | |
tree | 86d1c5c8be0cd6884170d6e3afcabdd6d82aa98d | |
parent | d83e426fff3f6d0fa6042d0930fb70357db24125 (diff) | |
download | librsvg-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.
-rw-r--r-- | rsvg-base.c | 89 | ||||
-rw-r--r-- | rsvg-io.c | 2 | ||||
-rw-r--r-- | rsvg-private.h | 4 |
3 files changed, 84 insertions, 11 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 * @@ -79,7 +79,7 @@ rsvg_acquire_data_data (const char *uri, gboolean base64 = FALSE; g_assert (out_len != NULL); - g_assert (g_str_has_prefix (uri, "data:")); + g_assert (strncmp (uri, "data:", 5) == 0); mime_type = NULL; start = uri + 5; diff --git a/rsvg-private.h b/rsvg-private.h index 25283d4b..1961eaf2 100644 --- a/rsvg-private.h +++ b/rsvg-private.h @@ -123,10 +123,10 @@ struct RsvgSaxHandler { }; typedef enum { - RSVG_LOAD_POLICY_ALL_PERMISSIVE + RSVG_LOAD_POLICY_STRICT } RsvgLoadPolicy; -#define RSVG_LOAD_POLICY_DEFAULT (RSVG_LOAD_POLICY_ALL_PERMISSIVE) +#define RSVG_LOAD_POLICY_DEFAULT (RSVG_LOAD_POLICY_STRICT) struct RsvgHandlePrivate { RsvgHandleFlags flags; |