Merge branch 'master' into allow-any-upstream-password

This commit is contained in:
Reshad Patuck 2020-10-01 09:59:19 +05:30 committed by GitHub
commit bbb59e3f95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 100 additions and 82 deletions

View File

@ -138,15 +138,12 @@ int
insert_acl (char *location, acl_access_t access_type, acl_list_t *access_list) insert_acl (char *location, acl_access_t access_type, acl_list_t *access_list)
{ {
struct acl_s acl; struct acl_s acl;
int ret; char *mask, ip_dst[IPV6_LEN];
char *p, ip_dst[IPV6_LEN];
assert (location != NULL); assert (location != NULL);
ret = init_access_list(access_list); if (init_access_list(access_list) != 0)
if (ret != 0) {
return -1; return -1;
}
/* /*
* Start populating the access control structure. * 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)); memset (&acl, 0, sizeof (struct acl_s));
acl.access = access_type; acl.access = access_type;
if ((mask = strrchr(location, '/')))
*(mask++) = 0;
/* /*
* Check for a valid IP address (the simplest case) first. * Check for a valid IP address (the simplest case) first.
*/ */
if (full_inet_pton (location, ip_dst) > 0) { if (full_inet_pton (location, ip_dst) > 0) {
acl.type = ACL_NUMERIC; acl.type = ACL_NUMERIC;
memcpy (acl.address.ip.network, ip_dst, IPV6_LEN); memcpy (acl.address.ip.network, ip_dst, IPV6_LEN);
memset (acl.address.ip.mask, 0xff, IPV6_LEN); if(!mask) memset (acl.address.ip.mask, 0xff, IPV6_LEN);
} else { 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) {
char dst[sizeof(struct in6_addr)]; char dst[sizeof(struct in6_addr)];
int v6; int v6, i;
/*
* 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;
/* Check if the IP address before the netmask is /* Check if the IP address before the netmask is
* an IPv6 address */ * an IPv6 address */
if (inet_pton(AF_INET6, location, dst) > 0) 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; v6 = 0;
if (fill_netmask_array if (fill_netmask_array
(p + 1, v6, &(acl.address.ip.mask[0]), IPV6_LEN) (mask, v6, &(acl.address.ip.mask[0]), IPV6_LEN)
< 0) < 0)
return -1; goto err;
for (i = 0; i < IPV6_LEN; i++) for (i = 0; i < IPV6_LEN; i++)
acl.address.ip.network[i] = ip_dst[i] & acl.address.ip.network[i] = ip_dst[i] &
acl.address.ip.mask[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; if(!sblist_add(*access_list, &acl)) return -1;
return 0; return 0;
err:;
/* restore mask for proper error message */
if(mask) *(--mask) = '/';
return -1;
} }
/* /*

View File

@ -68,7 +68,6 @@
# include <arpa/inet.h> # include <arpa/inet.h>
# include <grp.h> # include <grp.h>
# include <pwd.h> # include <pwd.h>
# include <regex.h>
/* rest - some oddball headers */ /* rest - some oddball headers */
#ifdef HAVE_VALUES_H #ifdef HAVE_VALUES_H

View File

@ -23,6 +23,7 @@
* add new directives to. Who knows if I'm right though. * add new directives to. Who knows if I'm right though.
*/ */
#include <regex.h>
#include "common.h" #include "common.h"
#include "conf.h" #include "conf.h"
@ -48,23 +49,25 @@
* can (and likely should) be used when building the regex for the * can (and likely should) be used when building the regex for the
* given directive. * given directive.
*/ */
#define WS "[[:space:]]+" #define DIGIT "[0-9]"
#define SPACE "[ \t]"
#define WS SPACE "+"
#define STR "\"([^\"]+)\"" #define STR "\"([^\"]+)\""
#define BOOL "(yes|on|no|off)" #define BOOL "(yes|on|no|off)"
#define INT "((0x)?[[:digit:]]+)" #define INT "(()" DIGIT "+)"
#define ALNUM "([-a-z0-9._]+)" #define ALNUM "([-a-z0-9._]+)"
#define USERNAME "([^:]*)" #define USERNAME "([^:]*)"
#define PASSWORD "(.*)" #define PASSWORD "(.*)"
#define IP "((([0-9]{1,3})\\.){3}[0-9]{1,3})" #define IP "((([0-9]{1,3})\\.){3}[0-9]{1,3})"
#define IPMASK "(" IP "(/[[:digit:]]+)?)" #define IPMASK "(" IP "(/" DIGIT "+)?)"
#define IPV6 "(" \ #define IPV6 "(" \
"(([0-9a-f:]{2,39}))|" \ "(([0-9a-f:]{2,39}))|" \
"(([0-9a-f:]{0,29}:" IP "))" \ "(([0-9a-f:]{0,29}:" IP "))" \
")" ")"
#define IPV6MASK "(" IPV6 "(/[[:digit:]]+)?)" #define IPV6MASK "(" IPV6 "(/" DIGIT "+)?)"
#define BEGIN "^[[:space:]]*" #define BEGIN "^" SPACE "*"
#define END "[[:space:]]*$" #define END SPACE "*$"
/* /*
* Limit the maximum number of substring matches to a reasonably high * Limit the maximum number of substring matches to a reasonably high
@ -73,6 +76,9 @@
*/ */
#define RE_MAX_MATCHES 24 #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 * All configuration handling functions are REQUIRED to be defined
* with the same function template as below. * with the same function template as below.
@ -637,9 +643,7 @@ static HANDLE_FUNC (handle_anonymous)
return -1; return -1;
if(anonymous_insert (conf, arg) < 0) { if(anonymous_insert (conf, arg) < 0) {
log_message (LOG_WARNING, CP_WARN ("anonymous_insert() failed: '%s'", arg);
"anonymous_insert() failed: '%s'",
arg);
safefree(arg); safefree(arg);
return -1; return -1;
} }
@ -767,7 +771,7 @@ static HANDLE_FUNC (handle_group)
} }
static void warn_invalid_address(char *arg, unsigned long lineno) { 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) static HANDLE_FUNC (handle_allow)
@ -812,8 +816,8 @@ static HANDLE_FUNC (handle_listen)
if (conf->listen_addrs == NULL) { if (conf->listen_addrs == NULL) {
conf->listen_addrs = sblist_new(sizeof(char*), 16); conf->listen_addrs = sblist_new(sizeof(char*), 16);
if (conf->listen_addrs == NULL) { if (conf->listen_addrs == NULL) {
log_message(LOG_WARNING, "Could not create a list " CP_WARN ("Could not create a list "
"of listen addresses."); "of listen addresses.", "");
safefree(arg); safefree(arg);
return -1; return -1;
} }
@ -839,9 +843,7 @@ static HANDLE_FUNC (handle_errorfile)
char *page = get_string_arg (line, &match[4]); char *page = get_string_arg (line, &match[4]);
if(add_new_errorpage (conf, page, err) < 0) { if(add_new_errorpage (conf, page, err) < 0) {
log_message (LOG_WARNING, CP_WARN ("add_new_errorpage() failed: '%s'", page);
"add_new_errorpage() failed: '%s'",
page);
safefree (page); safefree (page);
} }
return 0; return 0;
@ -1024,6 +1026,7 @@ static HANDLE_FUNC (handle_upstream)
int port, mi; int port, mi;
char *domain = 0, *user = 0, *pass = 0, *tmp; char *domain = 0, *user = 0, *pass = 0, *tmp;
enum proxy_type pt; enum proxy_type pt;
enum upstream_build_error ube;
if (match[3].rm_so != -1) { if (match[3].rm_so != -1) {
tmp = get_string_arg (line, &match[3]); tmp = get_string_arg (line, &match[3]);
@ -1033,9 +1036,9 @@ static HANDLE_FUNC (handle_upstream)
domain = get_string_arg (line, &match[4]); domain = get_string_arg (line, &match[4]);
if (!domain) if (!domain)
return -1; 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); safefree (domain);
return 0; goto check_err;
} }
} }
@ -1065,13 +1068,16 @@ static HANDLE_FUNC (handle_upstream)
if (match[mi].rm_so != -1) if (match[mi].rm_so != -1)
domain = get_string_arg (line, &match[mi]); 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 (user);
safefree (pass); safefree (pass);
safefree (domain); safefree (domain);
safefree (ip); safefree (ip);
check_err:;
if(ube != UBE_SUCCESS)
CP_WARN("%s", upstream_build_error_string(ube));
return 0; return 0;
} }

View File

@ -24,6 +24,7 @@
#include "main.h" #include "main.h"
#include <regex.h>
#include "filter.h" #include "filter.h"
#include "heap.h" #include "heap.h"
#include "log.h" #include "log.h"

View File

@ -20,6 +20,7 @@
* HTML error pages with variable substitution. * HTML error pages with variable substitution.
*/ */
#include <regex.h>
#include "main.h" #include "main.h"
#include "common.h" #include "common.h"

View File

@ -108,7 +108,7 @@ void set_log_level (int level)
void log_message (int level, const char *fmt, ...) void log_message (int level, const char *fmt, ...)
{ {
va_list args; va_list args;
time_t nowtime; struct timespec nowtime;
char time_string[TIME_LENGTH]; char time_string[TIME_LENGTH];
char str[STRING_LENGTH]; char str[STRING_LENGTH];
@ -174,13 +174,14 @@ void log_message (int level, const char *fmt, ...)
} else { } else {
char *p; char *p;
nowtime = time (NULL); clock_gettime(CLOCK_REALTIME, &nowtime);
/* Format is month day hour:minute:second (24 time) */ /* Format is month day hour:minute:second (24 time) */
strftime (time_string, TIME_LENGTH, "%b %d %H:%M:%S", 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, syslog_level[level], time_string,
nowtime.tv_nsec/1000000u,
(long int) getpid ()); (long int) getpid ());
/* /*

View File

@ -381,7 +381,7 @@ main (int argc, char **argv)
if (geteuid () == 0) if (geteuid () == 0)
change_user (argv[0]); change_user (argv[0]);
else else
log_message (LOG_WARNING, log_message (LOG_INFO,
"Not running as root, so not changing UID/GID."); "Not running as root, so not changing UID/GID.");
/* Create log file after we drop privileges */ /* Create log file after we drop privileges */

View File

@ -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. * Construct an upstream struct from input data.
*/ */
static struct upstream *upstream_build (const char *host, int port, const char *domain, static struct upstream *upstream_build (const char *host, int port, const char *domain,
const char *user, const char *pass, const char *user, const char *pass,
proxy_type type) proxy_type type, enum upstream_build_error *ube)
{ {
char *ptr; char *ptr;
struct upstream *up; struct upstream *up;
*ube = UBE_SUCCESS;
up = (struct upstream *) safemalloc (sizeof (struct upstream)); up = (struct upstream *) safemalloc (sizeof (struct upstream));
if (!up) { if (!up) {
log_message (LOG_ERR, *ube = UBE_OOM;
"Unable to allocate memory in upstream_build()");
return NULL; return NULL;
} }
@ -69,8 +83,7 @@ static struct upstream *upstream_build (const char *host, int port, const char *
ssize_t ret; ssize_t ret;
ret = basicauth_string(user, pass, b, sizeof b); ret = basicauth_string(user, pass, b, sizeof b);
if (ret == 0) { if (ret == 0) {
log_message (LOG_ERR, *ube = UBE_USERLEN;
"User / pass in upstream config too long");
return NULL; return NULL;
} }
up->ua.authstr = safestrdup (b); 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 (domain == NULL) {
if (type == PT_NONE) { if (type == PT_NONE) {
e_nonedomain:; e_nonedomain:;
log_message (LOG_WARNING, *ube = UBE_EDOMAIN;
"Nonsense upstream none rule: empty domain");
goto fail; goto fail;
} }
if (!host || !host[0] || port < 1) { if (!host || !host[0] || port < 1) {
log_message (LOG_WARNING, *ube = UBE_INVHOST;
"Nonsense upstream rule: invalid host or port");
goto fail; goto fail;
} }
@ -103,8 +114,7 @@ static struct upstream *upstream_build (const char *host, int port, const char *
if (!domain[0]) goto e_nonedomain; if (!domain[0]) goto e_nonedomain;
} else { } else {
if (!host || !host[0] || !domain[0]) { if (!host || !host[0] || !domain[0]) {
log_message (LOG_WARNING, *ube = UBE_INVPARAMS;
"Nonsense upstream rule: invalid parameters");
goto fail; goto fail;
} }
up->host = safestrdup (host); 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; up->ip = up->ip & up->mask;
} else { } else {
log_message (LOG_WARNING, *ube = UBE_NETMASK;
"Nonsense upstream rule: failed to parse netmask");
goto fail; goto fail;
} }
} else { } else {
@ -160,15 +169,17 @@ fail:
/* /*
* Add an entry to the upstream list * 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, const char *user, const char *pass,
proxy_type type, struct upstream **upstream_list) proxy_type type, struct upstream **upstream_list)
{ {
struct upstream *up; 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) { if (up == NULL) {
return; return ube;
} }
if (!up->domain && !up->ip) { /* always add default to end */ 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) { if (!tmp->next) {
up->next = NULL; up->next = NULL;
tmp->next = up; tmp->next = up;
return; return ube;
} }
tmp = tmp->next; tmp = tmp->next;
@ -194,14 +205,14 @@ void upstream_add (const char *host, int port, const char *domain,
up->next = *upstream_list; up->next = *upstream_list;
*upstream_list = up; *upstream_list = up;
return; return ube;
upstream_cleanup: upstream_cleanup:
safefree (up->host); safefree (up->host);
safefree (up->domain); safefree (up->domain);
safefree (up); safefree (up);
return; return ube;
} }
/* /*

View File

@ -27,6 +27,16 @@
#include "common.h" #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 * Even if upstream support is not compiled into tinyproxy, this
* structure still needs to be defined. * structure still needs to be defined.
@ -54,11 +64,13 @@ struct upstream {
#ifdef UPSTREAM_SUPPORT #ifdef UPSTREAM_SUPPORT
const char *proxy_type_name(proxy_type type); 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, const char *user, const char *pass,
proxy_type type, struct upstream **upstream_list); proxy_type type, struct upstream **upstream_list);
extern struct upstream *upstream_get (char *host, struct upstream *up); extern struct upstream *upstream_get (char *host, struct upstream *up);
extern void free_upstream_list (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 /* UPSTREAM_SUPPORT */
#endif /* _TINYPROXY_UPSTREAM_H_ */ #endif /* _TINYPROXY_UPSTREAM_H_ */