diff options
author | p37sitdu, corvid <devnull@localhost> | 2012-10-03 01:19:45 +0000 |
---|---|---|
committer | p37sitdu, corvid <devnull@localhost> | 2012-10-03 01:19:45 +0000 |
commit | 39ee4950acf53e63f0a8bf8cd7111f7ad282f6bb (patch) | |
tree | dc8779a49e158a5d0e9e4327543f672a41b1ec23 /src/domain.c | |
parent | 78003c727f7eae3a593260941aa4db6627dd1e75 (diff) |
introduce domainrc mechanism
Diffstat (limited to 'src/domain.c')
-rw-r--r-- | src/domain.c | 151 |
1 files changed, 151 insertions, 0 deletions
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; +} |