diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/cache.c | 4 | ||||
-rw-r--r-- | src/capi.c | 8 | ||||
-rw-r--r-- | src/dillo.cc | 7 | ||||
-rw-r--r-- | src/domain.c | 151 | ||||
-rw-r--r-- | src/domain.h | 19 | ||||
-rw-r--r-- | src/paths.hh | 1 |
7 files changed, 190 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 5e887d2c..05bbe00e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,6 +82,8 @@ dillo_SOURCES = \ dicache.h \ capi.c \ capi.h \ + domain.c \ + domain.h \ css.cc \ css.hh \ cssparser.cc \ diff --git a/src/cache.c b/src/cache.c index 97cbc458..4a689833 100644 --- a/src/cache.c +++ b/src/cache.c @@ -30,7 +30,7 @@ #include "capi.h" #include "decode.h" #include "auth.h" - +#include "domain.h" #include "timeout.hh" #include "uicmd.hh" @@ -682,7 +682,7 @@ static void Cache_parse_header(CacheEntry_t *entry) /* 30x: URL redirection */ DilloUrl *location_url = a_Url_new(location_str,URL_STR_(entry->Url)); - if (0) { + if (!a_Domain_permit(entry->Url, location_url)) { /* don't redirect; just show body like usual (if any) */ MSG("Redirection not followed from %s to %s\n", URL_HOST(entry->Url), URL_STR(location_url)); @@ -26,6 +26,7 @@ #include "nav.h" #include "dpiapi.h" #include "uicmd.hh" +#include "domain.h" #include "../dpip/dpip.h" /* for testing dpi chat */ @@ -378,6 +379,13 @@ int a_Capi_open_url(DilloWeb *web, CA_Callback_t Call, void *CbData) const char *scheme = URL_SCHEME(web->url); int safe = 0, ret = 0, use_cache = 0; + /* web->requester is NULL if the action is initiated by user */ + if (!(a_Capi_get_flags(web->url) & CAPI_IsCached || + web->requester == NULL || + a_Domain_permit(web->requester, web->url))) { + return 0; + } + /* reload test */ reload = (!(a_Capi_get_flags(web->url) & CAPI_IsCached) || (URL_FLAGS(web->url) & URL_E2EQuery)); diff --git a/src/dillo.cc b/src/dillo.cc index 2ac96810..3599ca7a 100644 --- a/src/dillo.cc +++ b/src/dillo.cc @@ -46,6 +46,7 @@ #include "capi.h" #include "dicache.h" #include "cookies.h" +#include "domain.h" #include "auth.h" #include "dw/fltkcore.hh" @@ -339,6 +340,11 @@ int main(int argc, char **argv) if ((fp = Paths::getPrefsFP(PATHS_RC_KEYS))) { Keys::parse(fp); } + // parse domainrc + if ((fp = Paths::getPrefsFP(PATHS_RC_DOMAIN))) { + a_Domain_parse(fp); + fclose(fp); + } dLib_show_messages(prefs.show_msg); // initialize internal modules @@ -442,6 +448,7 @@ int main(int argc, char **argv) * (This can be left to the OS, but we'll do it, with a view to test * and fix our memory management) */ + a_Domain_freeall(); a_Cookies_freeall(); a_Cache_freeall(); a_Dicache_freeall(); diff --git a/src/domain.c b/src/domain.c new file mode 100644 index 00000000..af8c8075 --- /dev/null +++ b/src/domain.c @@ -0,0 +1,151 @@ +/* + * File: domain.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + */ + +#include <stdlib.h> + +#include "../dlib/dlib.h" +#include "msg.h" +#include "list.h" +#include "domain.h" + +typedef struct Rule { + char *origin; + char *destination; +} Rule; + +static Rule *exceptions = NULL; +static int num_exceptions = 0; +static int num_exceptions_max = 1; + +static bool_t default_deny = FALSE; + +/* + * Parse domainrc. + */ +void a_Domain_parse(FILE *fp) +{ + char *line; + uint_t lineno = 0; + + MSG("Reading domainrc...\n"); + + while ((line = dGetline(fp)) != NULL) { + ++lineno; + + /* Remove leading and trailing whitespace */ + dStrstrip(line); + + if (line[0] && line[0] != '#') { + const char *delim = " \t"; + char *tok1 = strtok(line, delim); + char *tok2 = strtok(NULL, delim); + + if (strtok(NULL, delim) != NULL) { + MSG("Domain: Ignoring extraneous text at end of line %u.\n", + lineno); + } + if (!tok2) { + MSG("Domain: Not enough fields in line %u.\n", lineno); + } else { + if (dStrAsciiCasecmp(tok1, "default") == 0) { + if (dStrAsciiCasecmp(tok2, "deny") == 0) { + default_deny = TRUE; + MSG("Domain: Default deny.\n"); + } else if (dStrAsciiCasecmp(tok2, "accept") == 0) { + default_deny = FALSE; + MSG("Domain: Default accept.\n"); + } else { + MSG("Domain: Default action \"%s\" not recognised.\n", tok2); + } + } else { + a_List_add(exceptions, num_exceptions, num_exceptions_max); + exceptions[num_exceptions].origin = dStrdup(tok1); + exceptions[num_exceptions].destination = dStrdup(tok2); + num_exceptions++; + MSG("Domain: Exception from %s to %s.\n", tok1, tok2); + } + } + } + dFree(line); + } +} + +void a_Domain_freeall(void) +{ + int i = 0; + + for (i = 0; i < num_exceptions; i++) { + dFree(exceptions[i].origin); + dFree(exceptions[i].destination); + } + dFree(exceptions); +} + +/* + * Wildcard ('*') pattern always matches. + * "example.org" pattern matches "example.org". + * ".example.org" pattern matches "example.org" and "sub.example.org". + */ +static bool_t Domain_match(const char *host, const char *pattern) { + int cmp = strcmp(pattern, "*"); + + if (cmp) { + if (pattern[0] != '.') + cmp = dStrAsciiCasecmp(host, pattern); + else { + int diff = strlen(host) - strlen(pattern); + + if (diff == -1) + cmp = dStrAsciiCasecmp(host, pattern + 1); + else if (diff >= 0) + cmp = dStrAsciiCasecmp(host + diff, pattern); + } + } + return cmp ? FALSE : TRUE; +} + +/* + * Is the resource at 'source' permitted to request the resource at 'dest'? + */ +bool_t a_Domain_permit(const DilloUrl *source, const DilloUrl *dest) +{ + int i; + bool_t ret; + const char *source_host, *dest_host; + + if (default_deny == FALSE && num_exceptions == 0) + return TRUE; + + source_host = URL_HOST(source); + dest_host = URL_HOST(dest); + + if (dest_host[0] == '\0') + return source_host[0] == '\0' || + !dStrAsciiCasecmp(URL_SCHEME(dest), "data"); + + if (a_Url_same_organization(source, dest)) + return TRUE; + + for (i = 0; i < num_exceptions; i++) { + if(Domain_match(source_host, exceptions[i].origin) && + Domain_match(dest_host, exceptions[i].destination)) { + ret = default_deny; + MSG("Domain: Matched rule from %s to %s.\n", exceptions[i].origin, + exceptions[i].destination); + break; + } + } + if (i == num_exceptions) + ret = default_deny ? FALSE : TRUE; + + MSG("Domain: %s from %s to %s.\n", + (ret == TRUE ? "permitted" : "DENIED"), source_host, dest_host); + + return ret; +} diff --git a/src/domain.h b/src/domain.h new file mode 100644 index 00000000..d1ca685b --- /dev/null +++ b/src/domain.h @@ -0,0 +1,19 @@ +#ifndef __DOMAIN_H__ +#define __DOMAIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include "url.h" + +void a_Domain_parse(FILE *fp); +void a_Domain_freeall(void); +bool_t a_Domain_permit(const DilloUrl *source, const DilloUrl *dest); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/paths.hh b/src/paths.hh index a9efc62b..8f52cd86 100644 --- a/src/paths.hh +++ b/src/paths.hh @@ -14,6 +14,7 @@ #define PATHS_RC_PREFS "dillorc" #define PATHS_RC_KEYS "keysrc" +#define PATHS_RC_DOMAIN "domainrc" class Paths { public: |