summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorp37sitdu, corvid <devnull@localhost>2012-10-03 01:19:45 +0000
committerp37sitdu, corvid <devnull@localhost>2012-10-03 01:19:45 +0000
commit39ee4950acf53e63f0a8bf8cd7111f7ad282f6bb (patch)
treedc8779a49e158a5d0e9e4327543f672a41b1ec23 /src
parent78003c727f7eae3a593260941aa4db6627dd1e75 (diff)
introduce domainrc mechanism
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/cache.c4
-rw-r--r--src/capi.c8
-rw-r--r--src/dillo.cc7
-rw-r--r--src/domain.c151
-rw-r--r--src/domain.h19
-rw-r--r--src/paths.hh1
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));
diff --git a/src/capi.c b/src/capi.c
index db8e6b87..1da2d9ca 100644
--- a/src/capi.c
+++ b/src/capi.c
@@ -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: