diff --git a/src/acl.c b/src/acl.c index 261b7dd..b989219 100644 --- a/src/acl.c +++ b/src/acl.c @@ -138,15 +138,12 @@ int insert_acl (char *location, acl_access_t access_type, acl_list_t *access_list) { struct acl_s acl; - int ret; - char *p, ip_dst[IPV6_LEN]; + char *mask, ip_dst[IPV6_LEN]; assert (location != NULL); - ret = init_access_list(access_list); - if (ret != 0) { + if (init_access_list(access_list) != 0) return -1; - } /* * Start populating the access control structure. @@ -154,38 +151,19 @@ insert_acl (char *location, acl_access_t access_type, acl_list_t *access_list) memset (&acl, 0, sizeof (struct acl_s)); acl.access = access_type; + if ((mask = strrchr(location, '/'))) + *(mask++) = 0; + /* * Check for a valid IP address (the simplest case) first. */ if (full_inet_pton (location, ip_dst) > 0) { acl.type = ACL_NUMERIC; memcpy (acl.address.ip.network, ip_dst, IPV6_LEN); - memset (acl.address.ip.mask, 0xff, IPV6_LEN); - } else { - int i; - /* bogus ipv6 ? */ - if (strchr (location, ':')) - return -1; - - /* - * At this point we're either a hostname or an - * IP address with a slash. - */ - p = strchr (location, '/'); - if (p != NULL) { + if(!mask) memset (acl.address.ip.mask, 0xff, IPV6_LEN); + else { char dst[sizeof(struct in6_addr)]; - int v6; - - /* - * We have a slash, so it's intended to be an - * IP address with mask - */ - *p = '\0'; - if (full_inet_pton (location, ip_dst) <= 0) - return -1; - - acl.type = ACL_NUMERIC; - + int v6, i; /* Check if the IP address before the netmask is * an IPv6 address */ if (inet_pton(AF_INET6, location, dst) > 0) @@ -194,24 +172,33 @@ insert_acl (char *location, acl_access_t access_type, acl_list_t *access_list) v6 = 0; if (fill_netmask_array - (p + 1, v6, &(acl.address.ip.mask[0]), IPV6_LEN) + (mask, v6, &(acl.address.ip.mask[0]), IPV6_LEN) < 0) - return -1; + goto err; for (i = 0; i < IPV6_LEN; i++) acl.address.ip.network[i] = ip_dst[i] & acl.address.ip.mask[i]; - } else { - /* In all likelihood a string */ - acl.type = ACL_STRING; - acl.address.string = safestrdup (location); - if (!acl.address.string) - return -1; } + } else { + /* either bogus IP or hostname */ + /* bogus ipv6 ? */ + if (mask || strchr (location, ':')) + goto err; + + /* In all likelihood a string */ + acl.type = ACL_STRING; + acl.address.string = safestrdup (location); + if (!acl.address.string) + goto err; } if(!sblist_add(*access_list, &acl)) return -1; return 0; +err:; + /* restore mask for proper error message */ + if(mask) *(--mask) = '/'; + return -1; } /* diff --git a/src/common.h b/src/common.h index 47a1ed1..563ee6f 100644 --- a/src/common.h +++ b/src/common.h @@ -68,7 +68,6 @@ # include # include # include -# include /* rest - some oddball headers */ #ifdef HAVE_VALUES_H diff --git a/src/conf.c b/src/conf.c index c16f55e..f2b9964 100644 --- a/src/conf.c +++ b/src/conf.c @@ -23,6 +23,7 @@ * add new directives to. Who knows if I'm right though. */ +#include #include "common.h" #include "conf.h" @@ -48,23 +49,25 @@ * can (and likely should) be used when building the regex for the * given directive. */ -#define WS "[[:space:]]+" +#define DIGIT "[0-9]" +#define SPACE "[ \t]" +#define WS SPACE "+" #define STR "\"([^\"]+)\"" #define BOOL "(yes|on|no|off)" -#define INT "((0x)?[[:digit:]]+)" +#define INT "(()" DIGIT "+)" #define ALNUM "([-a-z0-9._]+)" #define USERNAME "([^:]*)" #define PASSWORD "(.*)" #define IP "((([0-9]{1,3})\\.){3}[0-9]{1,3})" -#define IPMASK "(" IP "(/[[:digit:]]+)?)" +#define IPMASK "(" IP "(/" DIGIT "+)?)" #define IPV6 "(" \ "(([0-9a-f:]{2,39}))|" \ "(([0-9a-f:]{0,29}:" IP "))" \ ")" -#define IPV6MASK "(" IPV6 "(/[[:digit:]]+)?)" -#define BEGIN "^[[:space:]]*" -#define END "[[:space:]]*$" +#define IPV6MASK "(" IPV6 "(/" DIGIT "+)?)" +#define BEGIN "^" SPACE "*" +#define END SPACE "*$" /* * Limit the maximum number of substring matches to a reasonably high @@ -73,6 +76,9 @@ */ #define RE_MAX_MATCHES 24 +#define CP_WARN(FMT, ...) \ + log_message (LOG_WARNING, "line %lu: " FMT, lineno, __VA_ARGS__) + /* * All configuration handling functions are REQUIRED to be defined * with the same function template as below. @@ -637,9 +643,7 @@ static HANDLE_FUNC (handle_anonymous) return -1; if(anonymous_insert (conf, arg) < 0) { - log_message (LOG_WARNING, - "anonymous_insert() failed: '%s'", - arg); + CP_WARN ("anonymous_insert() failed: '%s'", arg); safefree(arg); return -1; } @@ -767,7 +771,7 @@ static HANDLE_FUNC (handle_group) } static void warn_invalid_address(char *arg, unsigned long lineno) { - log_message (LOG_WARNING, "Invalid address %s on line %lu", arg, lineno); + CP_WARN ("Invalid address %s", arg); } static HANDLE_FUNC (handle_allow) @@ -812,8 +816,8 @@ static HANDLE_FUNC (handle_listen) if (conf->listen_addrs == NULL) { conf->listen_addrs = sblist_new(sizeof(char*), 16); if (conf->listen_addrs == NULL) { - log_message(LOG_WARNING, "Could not create a list " - "of listen addresses."); + CP_WARN ("Could not create a list " + "of listen addresses.", ""); safefree(arg); return -1; } @@ -839,9 +843,7 @@ static HANDLE_FUNC (handle_errorfile) char *page = get_string_arg (line, &match[4]); if(add_new_errorpage (conf, page, err) < 0) { - log_message (LOG_WARNING, - "add_new_errorpage() failed: '%s'", - page); + CP_WARN ("add_new_errorpage() failed: '%s'", page); safefree (page); } return 0; @@ -1024,6 +1026,7 @@ static HANDLE_FUNC (handle_upstream) int port, mi; char *domain = 0, *user = 0, *pass = 0, *tmp; enum proxy_type pt; + enum upstream_build_error ube; if (match[3].rm_so != -1) { tmp = get_string_arg (line, &match[3]); @@ -1033,9 +1036,9 @@ static HANDLE_FUNC (handle_upstream) domain = get_string_arg (line, &match[4]); if (!domain) return -1; - upstream_add (NULL, 0, domain, 0, 0, PT_NONE, &conf->upstream_list); + ube = upstream_add (NULL, 0, domain, 0, 0, PT_NONE, &conf->upstream_list); safefree (domain); - return 0; + goto check_err; } } @@ -1065,13 +1068,16 @@ static HANDLE_FUNC (handle_upstream) if (match[mi].rm_so != -1) domain = get_string_arg (line, &match[mi]); - upstream_add (ip, port, domain, user, pass, pt, &conf->upstream_list); + ube = upstream_add (ip, port, domain, user, pass, pt, &conf->upstream_list); safefree (user); safefree (pass); safefree (domain); safefree (ip); +check_err:; + if(ube != UBE_SUCCESS) + CP_WARN("%s", upstream_build_error_string(ube)); return 0; } diff --git a/src/filter.c b/src/filter.c index 8a0b085..d70cb59 100644 --- a/src/filter.c +++ b/src/filter.c @@ -24,6 +24,7 @@ #include "main.h" +#include #include "filter.h" #include "heap.h" #include "log.h" diff --git a/src/html-error.c b/src/html-error.c index 7c71f74..78c3ef0 100644 --- a/src/html-error.c +++ b/src/html-error.c @@ -20,6 +20,7 @@ * HTML error pages with variable substitution. */ +#include #include "main.h" #include "common.h" diff --git a/src/log.c b/src/log.c index dc76c1a..873abb2 100644 --- a/src/log.c +++ b/src/log.c @@ -108,7 +108,7 @@ void set_log_level (int level) void log_message (int level, const char *fmt, ...) { va_list args; - time_t nowtime; + struct timespec nowtime; char time_string[TIME_LENGTH]; char str[STRING_LENGTH]; @@ -174,13 +174,14 @@ void log_message (int level, const char *fmt, ...) } else { char *p; - nowtime = time (NULL); + clock_gettime(CLOCK_REALTIME, &nowtime); /* Format is month day hour:minute:second (24 time) */ strftime (time_string, TIME_LENGTH, "%b %d %H:%M:%S", - localtime (&nowtime)); + localtime (&nowtime.tv_sec)); - snprintf (str, STRING_LENGTH, "%-9s %s [%ld]: ", + snprintf (str, STRING_LENGTH, "%-9s %s.%03u [%ld]: ", syslog_level[level], time_string, + nowtime.tv_nsec/1000000u, (long int) getpid ()); /* diff --git a/src/main.c b/src/main.c index c478ccf..1309284 100644 --- a/src/main.c +++ b/src/main.c @@ -381,7 +381,7 @@ main (int argc, char **argv) if (geteuid () == 0) change_user (argv[0]); else - log_message (LOG_WARNING, + log_message (LOG_INFO, "Not running as root, so not changing UID/GID."); /* Create log file after we drop privileges */ diff --git a/src/upstream.c b/src/upstream.c index 0f7f24f..c8fee22 100644 --- a/src/upstream.c +++ b/src/upstream.c @@ -43,20 +43,34 @@ proxy_type_name(proxy_type type) } } + +const char* upstream_build_error_string(enum upstream_build_error ube) { + static const char *emap[] = { + [UBE_SUCCESS] = "", + [UBE_OOM] = "Unable to allocate memory in upstream_build()", + [UBE_USERLEN] = "User / pass in upstream config too long", + [UBE_EDOMAIN] = "Nonsense upstream none rule: empty domain", + [UBE_INVHOST] = "Nonsense upstream rule: invalid host or port", + [UBE_INVPARAMS] = "Nonsense upstream rule: invalid parameters", + [UBE_NETMASK] = "Nonsense upstream rule: failed to parse netmask", + }; + return emap[ube]; +} + /** * Construct an upstream struct from input data. */ static struct upstream *upstream_build (const char *host, int port, const char *domain, const char *user, const char *pass, - proxy_type type) + proxy_type type, enum upstream_build_error *ube) { char *ptr; struct upstream *up; + *ube = UBE_SUCCESS; up = (struct upstream *) safemalloc (sizeof (struct upstream)); if (!up) { - log_message (LOG_ERR, - "Unable to allocate memory in upstream_build()"); + *ube = UBE_OOM; return NULL; } @@ -69,8 +83,7 @@ static struct upstream *upstream_build (const char *host, int port, const char * ssize_t ret; ret = basicauth_string(user, pass, b, sizeof b); if (ret == 0) { - log_message (LOG_ERR, - "User / pass in upstream config too long"); + *ube = UBE_USERLEN; return NULL; } up->ua.authstr = safestrdup (b); @@ -83,13 +96,11 @@ static struct upstream *upstream_build (const char *host, int port, const char * if (domain == NULL) { if (type == PT_NONE) { e_nonedomain:; - log_message (LOG_WARNING, - "Nonsense upstream none rule: empty domain"); + *ube = UBE_EDOMAIN; goto fail; } if (!host || !host[0] || port < 1) { - log_message (LOG_WARNING, - "Nonsense upstream rule: invalid host or port"); + *ube = UBE_INVHOST; goto fail; } @@ -103,8 +114,7 @@ static struct upstream *upstream_build (const char *host, int port, const char * if (!domain[0]) goto e_nonedomain; } else { if (!host || !host[0] || !domain[0]) { - log_message (LOG_WARNING, - "Nonsense upstream rule: invalid parameters"); + *ube = UBE_INVPARAMS; goto fail; } up->host = safestrdup (host); @@ -130,8 +140,7 @@ static struct upstream *upstream_build (const char *host, int port, const char * } up->ip = up->ip & up->mask; } else { - log_message (LOG_WARNING, - "Nonsense upstream rule: failed to parse netmask"); + *ube = UBE_NETMASK; goto fail; } } else { @@ -160,15 +169,17 @@ fail: /* * Add an entry to the upstream list */ -void upstream_add (const char *host, int port, const char *domain, +enum upstream_build_error upstream_add ( + const char *host, int port, const char *domain, const char *user, const char *pass, proxy_type type, struct upstream **upstream_list) { struct upstream *up; + enum upstream_build_error ube; - up = upstream_build (host, port, domain, user, pass, type); + up = upstream_build (host, port, domain, user, pass, type, &ube); if (up == NULL) { - return; + return ube; } if (!up->domain && !up->ip) { /* always add default to end */ @@ -184,7 +195,7 @@ void upstream_add (const char *host, int port, const char *domain, if (!tmp->next) { up->next = NULL; tmp->next = up; - return; + return ube; } tmp = tmp->next; @@ -194,14 +205,14 @@ void upstream_add (const char *host, int port, const char *domain, up->next = *upstream_list; *upstream_list = up; - return; + return ube; upstream_cleanup: safefree (up->host); safefree (up->domain); safefree (up); - return; + return ube; } /* diff --git a/src/upstream.h b/src/upstream.h index c112784..a611807 100644 --- a/src/upstream.h +++ b/src/upstream.h @@ -27,6 +27,16 @@ #include "common.h" +enum upstream_build_error { + UBE_SUCCESS = 0, + UBE_OOM, + UBE_USERLEN, + UBE_EDOMAIN, + UBE_INVHOST, + UBE_INVPARAMS, + UBE_NETMASK, +}; + /* * Even if upstream support is not compiled into tinyproxy, this * structure still needs to be defined. @@ -54,11 +64,13 @@ struct upstream { #ifdef UPSTREAM_SUPPORT const char *proxy_type_name(proxy_type type); -extern void upstream_add (const char *host, int port, const char *domain, +extern enum upstream_build_error upstream_add ( + const char *host, int port, const char *domain, const char *user, const char *pass, proxy_type type, struct upstream **upstream_list); extern struct upstream *upstream_get (char *host, struct upstream *up); extern void free_upstream_list (struct upstream *up); +extern const char* upstream_build_error_string(enum upstream_build_error); #endif /* UPSTREAM_SUPPORT */ #endif /* _TINYPROXY_UPSTREAM_H_ */