Merge branch 'master' into x-forwarded-for

This commit is contained in:
Vladimir Belov 2018-09-27 17:22:58 +03:00 committed by GitHub
commit 1eacdc32ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 695 additions and 527 deletions

82
AUTHORS
View File

@ -1,43 +1,39 @@
Tinyproxy AUTHORS Andrew Stribblehill
================= bertliao
Bob Showalter
//// Brian Cain
This file is generated from authors.xml, do not edit it directly. cvs2svn
//// Daniel Egger
Daniel M. Drucker
Coding David Shanks
------ Dmitry Semyonov
dmz-uk
The following people have contributed code to Tinyproxy: Drew G. Wallace
Frank Morgner
* Andrew Stribblehill gary-wzl77
* Chris Lightfoot Gaudenz Steinlin
* Daniel Egger goba62000374
* David Shanks Gonzalo Tornaria
* Dmitry Semyonov Greg
* George Talusan Jeremy Hinegardner
* James E. Flemer John Spencer
* Jeremy Hinegardner John van der Kamp
* John van der Kamp John Weldon
* Jordi Mallach Jordi
* Kim Holviala Jordi Mallach
* Mathew Mrosko Julien Hartmann
* Matthew Dempsky kikuchan
* Michael Adam Mathew Mrosko
* Moritz Muehlenhoff Matthew Dempsky
* Mukund Sivaraman Michael Adam
* Petr Lampa Mike Mead
* Robert James Kaes Mukund Sivaraman
* Steven Young Pablo Panero
Peter H. Froehlich
Robert James Kaes
Documentation rofl0r
------------- Stephan Leemburg
Steven Conaway
The following people have helped to document Tinyproxy: Steven Young
Valen Blanco
* Marc Silver Vladimir Belov
* Michael Adam
* Mukund Sivaraman
* Robert James Kaes
* Steven Young

View File

@ -4,27 +4,13 @@ SUBDIRS = \
etc \ etc \
docs \ docs \
m4macros \ m4macros \
tests tests \
scripts
# tools want this on a single line # tools want this on a single line
ACLOCAL_AMFLAGS = -I m4macros ACLOCAL_AMFLAGS = -I m4macros
AUTHORS: authors.xml authors.xsl all-local:
if HAVE_XSLTPROC
$(AM_V_GEN) $(XSLTPROC) authors.xsl $< > $(@) || rm -f $(@)
else
@echo "*** xsltproc is required to regenerate $(@) ***"; exit 1;
endif
validate-authors:
if HAVE_XMLLINT
@$(XMLLINT) --noout --path $(srcdir) --valid authors.xml || \
( echo "*** authors.xml IS INVALID ***"; exit 1; )
endif
all-local: AUTHORS
check-local: validate-authors
dist_doc_DATA = \ dist_doc_DATA = \
AUTHORS \ AUTHORS \
@ -33,12 +19,10 @@ dist_doc_DATA = \
README.md README.md
EXTRA_DIST = \ EXTRA_DIST = \
authors.dtd \
authors.xml \
authors.xsl \
autogen.sh \ autogen.sh \
tinyproxy-indent.sh \ tinyproxy-indent.sh \
TODO TODO \
VERSION
test: all test: all
./tests/scripts/run_tests.sh ./tests/scripts/run_tests.sh

13
NEWS
View File

@ -1,12 +1 @@
Tinyproxy NEWS See git log for recent changes in Tinyproxy.
==============
Version 1.9.0
-------------
Bugs fixed
~~~~~~~~~~
Contributors
~~~~~~~~~~~~

View File

@ -26,7 +26,7 @@ system. If compiling from a git checkout, you need to first run
from the top level directory to generate the `configure` script. from the top level directory to generate the `configure` script.
The release tarball contains the pre-created `configure` script, The release tarball contains the pre-created `configure` script,
so when building fom a release, you can skip this step. so when building from a release, you can skip this step.
Then basically all you need to do is Then basically all you need to do is
@ -56,9 +56,6 @@ Enable support for proxying connections through another proxy server.
- `--enable-transparent`: - `--enable-transparent`:
Allow Tinyproxy to be used as a transparent proxy daemon. Allow Tinyproxy to be used as a transparent proxy daemon.
- `--enable-static`:
Compile a static version of Tinyproxy.
- `--enable-reverse`: - `--enable-reverse`:
Enable reverse proxying. Enable reverse proxying.

1
VERSION Normal file
View File

@ -0,0 +1 @@
1.10.0

View File

@ -1,12 +0,0 @@
<!--
Simple DTD for Tinyproxy authors. This file was adapted from GIMP.
-->
<!ELEMENT authors (contributor+)>
<!ATTLIST authors xmlns CDATA #FIXED "http://purl.org/dc/elements/1.1/">
<!ELEMENT contributor (#PCDATA)>
<!ATTLIST contributor role CDATA #REQUIRED>
<!ATTLIST contributor last-active CDATA #REQUIRED>

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE authors SYSTEM "authors.dtd">
<!--
This file is supposed to list all authors and contributors. It's in
XML format so that it can easily be used in source code. When
changing this file, please keep the alphabetical order. This file
was adapted from GIMP.
-->
<authors xmlns="http://purl.org/dc/elements/1.1/">
<contributor role="author" last-active="1.7">Andrew Stribblehill</contributor>
<contributor role="author" last-active="1.6">Chris Lightfoot</contributor>
<contributor role="author" last-active="1.8">Daniel Egger</contributor>
<contributor role="author" last-active="1.8">David Shanks</contributor>
<contributor role="author" last-active="1.8">Dmitry Semyonov</contributor>
<contributor role="author" last-active="1.6">George Talusan</contributor>
<contributor role="author" last-active="1.6">James E. Flemer</contributor>
<contributor role="author" last-active="1.7">Jeremy Hinegardner</contributor>
<contributor role="author" last-active="1.8">John van der Kamp</contributor>
<contributor role="author" last-active="1.8">Jordi Mallach</contributor>
<contributor role="author" last-active="1.7">Kim Holviala</contributor>
<contributor role="documenter" last-active="1.7">Marc Silver</contributor>
<contributor role="author" last-active="1.8">Mathew Mrosko</contributor>
<contributor role="author" last-active="1.7">Matthew Dempsky</contributor>
<contributor role="author,documenter" last-active="1.8">Michael Adam</contributor>
<contributor role="author" last-active="1.8">Moritz Muehlenhoff</contributor>
<contributor role="author,documenter" last-active="1.8">Mukund Sivaraman</contributor>
<contributor role="author" last-active="1.6">Petr Lampa</contributor>
<contributor role="author,documenter" last-active="1.7">Robert James Kaes</contributor>
<contributor role="author,documenter" last-active="1.7">Steven Young</contributor>
</authors>

View File

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Simple XSL transformation to create a text version AUTHORS file from
authors.xml. This file was adapted from GIMP.
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<xsl:output method="text" />
<xsl:template name="contributor">
<xsl:param name="role" />
<xsl:apply-templates select="dc:contributor[contains(@role, $role)]" />
</xsl:template>
<xsl:template match="/dc:authors">
<xsl:text>Tinyproxy AUTHORS
=================
////
This file is generated from authors.xml, do not edit it directly.
////
Coding
------
The following people have contributed code to Tinyproxy:
</xsl:text>
<xsl:call-template name="contributor">
<xsl:with-param name="role" select="'author'"/>
</xsl:call-template>
<xsl:text>
Documentation
-------------
The following people have helped to document Tinyproxy:
</xsl:text>
<xsl:call-template name="contributor">
<xsl:with-param name="role" select="'documenter'"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="dc:contributor">
<xsl:text> * </xsl:text><xsl:apply-templates /><xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>

View File

@ -3,20 +3,7 @@
AC_PREREQ(2.54) AC_PREREQ(2.54)
m4_define([tinyproxy_major_version], [1]) m4_define([tinyproxy_version], esyscmd(sh scripts/version.sh | tr -d '\n'))
m4_define([tinyproxy_minor_version], [9])
m4_define([tinyproxy_micro_version], [0])
m4_define([tinyproxy_real_version],
[tinyproxy_major_version.tinyproxy_minor_version.tinyproxy_micro_version])
m4_define([tinyproxy_version], [tinyproxy_real_version])
# For overriding the version string. Comment out if not needed.
# m4_define([tinyproxy_version], [1.9.0])
m4_define([tinyproxy_unstable],
m4_if(m4_eval(tinyproxy_minor_version % 2), [1], [yes], [no]))
m4_define([tinyproxy_stable],
m4_if(m4_eval(tinyproxy_minor_version % 2), [0], [yes], [no]))
AC_INIT([Tinyproxy], [tinyproxy_version], AC_INIT([Tinyproxy], [tinyproxy_version],
[https://tinyproxy.github.io/], [https://tinyproxy.github.io/],
@ -29,31 +16,9 @@ AC_CONFIG_MACRO_DIR([m4macros])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
TINYPROXY_MAJOR_VERSION=tinyproxy_major_version
TINYPROXY_MINOR_VERSION=tinyproxy_minor_version
TINYPROXY_MICRO_VERSION=tinyproxy_micro_version
TINYPROXY_REAL_VERSION=tinyproxy_real_version
TINYPROXY_VERSION=tinyproxy_version
TINYPROXY_UNSTABLE=tinyproxy_unstable
AC_SUBST(TINYPROXY_MAJOR_VERSION)
AC_SUBST(TINYPROXY_MINOR_VERSION)
AC_SUBST(TINYPROXY_MICRO_VERSION)
AC_SUBST(TINYPROXY_REAL_VERSION)
AC_SUBST(TINYPROXY_VERSION)
AC_SUBST(TINYPROXY_UNSTABLE)
dnl Temporarily defined here until we get tinyproxy-version.h dnl Temporarily defined here until we get tinyproxy-version.h
AC_DEFINE(TINYPROXY_VERSION, "tinyproxy_version", [Tinyproxy version number]) AC_DEFINE(TINYPROXY_VERSION, "tinyproxy_version", [Tinyproxy version number])
# The symbol TINYPROXY_UNSTABLE is defined above for substitution in
# Makefiles and conditionally defined here as a preprocessor symbol
# and automake conditional.
if test "x$TINYPROXY_UNSTABLE" = "xyes"; then
AC_DEFINE(TINYPROXY_UNSTABLE, 1,
[Define to 1 if this is an unstable version of Tinyproxy])
fi
AM_CONDITIONAL(TINYPROXY_UNSTABLE, test "x$TINYPROXY_UNSTABLE" = "xyes")
dnl Check if we're compiling on a weird platform :) dnl Check if we're compiling on a weird platform :)
AC_USE_SYSTEM_EXTENSIONS AC_USE_SYSTEM_EXTENSIONS
@ -113,8 +78,8 @@ dnl Include support for reverse proxy?
AH_TEMPLATE([REVERSE_SUPPORT], AH_TEMPLATE([REVERSE_SUPPORT],
[Include support for reverse proxy.]) [Include support for reverse proxy.])
TP_ARG_ENABLE(reverse, TP_ARG_ENABLE(reverse,
[Enable reverse proxying (default is NO)], [Enable reverse proxying (default is YES)],
no) yes)
if test x"$reverse_enabled" = x"yes"; then if test x"$reverse_enabled" = x"yes"; then
ADDITIONAL_OBJECTS="$ADDITIONAL_OBJECTS reverse-proxy.o" ADDITIONAL_OBJECTS="$ADDITIONAL_OBJECTS reverse-proxy.o"
AC_DEFINE(REVERSE_SUPPORT) AC_DEFINE(REVERSE_SUPPORT)
@ -124,8 +89,8 @@ dnl Include the transparent proxy support
AH_TEMPLATE([TRANSPARENT_PROXY], AH_TEMPLATE([TRANSPARENT_PROXY],
[Include support for using tinyproxy as a transparent proxy.]) [Include support for using tinyproxy as a transparent proxy.])
TP_ARG_ENABLE(transparent, TP_ARG_ENABLE(transparent,
[Enable transparent proxying code (default is NO)], [Enable transparent proxying code (default is YES)],
no) yes)
if test x"$transparent_enabled" = x"yes"; then if test x"$transparent_enabled" = x"yes"; then
ADDITIONAL_OBJECTS="$ADDITIONAL_OBJECTS transparent-proxy.o" ADDITIONAL_OBJECTS="$ADDITIONAL_OBJECTS transparent-proxy.o"
AC_DEFINE(TRANSPARENT_PROXY) AC_DEFINE(TRANSPARENT_PROXY)
@ -173,7 +138,7 @@ AC_CHECK_FUNCS([inet_ntoa strdup])
AC_CHECK_FUNCS([strlcpy strlcat setgroups]) AC_CHECK_FUNCS([strlcpy strlcat setgroups])
dnl Enable extra warnings dnl Enable extra warnings
DESIRED_FLAGS="-fdiagnostics-show-option -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Wfloat-equal -Wundef -Wformat=2 -Wlogical-op -Wmissing-include-dirs -Wformat-nonliteral -Wold-style-definition -Wpointer-arith -Waggregate-return -Winit-self -Wpacked --std=c89 -ansi -pedantic -Wno-overlength-strings -Wc++-compat -Wno-long-long -Wno-overlength-strings -Wdeclaration-after-statement -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wcast-qual -Wcast-align -Wwrite-strings -Wp,-D_FORTIFY_SOURCE=2 -fno-common" DESIRED_FLAGS="-fdiagnostics-show-option -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Wfloat-equal -Wundef -Wformat=2 -Wlogical-op -Wmissing-include-dirs -Wformat-nonliteral -Wold-style-definition -Wpointer-arith -Waggregate-return -Winit-self -Wpacked --std=c89 -ansi -Wno-overlength-strings -Wno-long-long -Wno-overlength-strings -Wdeclaration-after-statement -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wcast-qual -Wcast-align -Wwrite-strings -Wp,-D_FORTIFY_SOURCE=2 -fno-common"
if test -n "${MAINTAINER_MODE_FALSE}"; then if test -n "${MAINTAINER_MODE_FALSE}"; then
DESIRED_FLAGS="-Werror $DESIRED_FLAGS" DESIRED_FLAGS="-Werror $DESIRED_FLAGS"
@ -245,6 +210,7 @@ docs/man8/tinyproxy.txt
m4macros/Makefile m4macros/Makefile
tests/Makefile tests/Makefile
tests/scripts/Makefile tests/scripts/Makefile
scripts/Makefile
]) ])
AC_OUTPUT AC_OUTPUT

View File

@ -144,21 +144,25 @@ The possible keywords and their descriptions are as follows:
`X-Tinyproxy` containing the client's IP address to the request. `X-Tinyproxy` containing the client's IP address to the request.
*Upstream*:: *Upstream*::
*No Upstream*::
This option allows you to set up a set of rules for deciding This option allows you to set up a set of rules for deciding
whether an upstream proxy server is to be used, based on the whether an upstream proxy server is to be used, based on the
host or domain of the site being accessed. The rules are stored host or domain of the site being accessed. The rules are stored
in the order encountered in the configuration file and the in the order encountered in the configuration file and the
LAST matching rule wins. There are three possible forms for LAST matching rule wins. The following forms for specifying upstream
specifying upstream rules: rules exist:
* 'upstream host:port' turns proxy upstream support on generally. * 'upstream type host:port' turns proxy upstream support on generally.
* 'upstream host:port "site_spec"' turns on the upstream proxy for * 'upstream type user:pass@host:port' does the same, but uses the
the sites matching `site_spec`. supplied credentials for authentication.
* 'no upstream "site_spec"' turns off upstream support for sites * 'upstream type host:port "site_spec"' turns on the upstream proxy
for the sites matching `site_spec`.
`type` can be one of `http`, `socks4`, `socks5`, `none`.
* 'upstream none "site_spec"' turns off upstream support for sites
matching `site_spec`. matching `site_spec`.
The site can be specified in various forms as a hostname, domain The site can be specified in various forms as a hostname, domain
@ -368,10 +372,7 @@ This manpage was written by the Tinyproxy project team.
COPYRIGHT COPYRIGHT
--------- ---------
Copyright (c) 1998-2000 Steven Young; Copyright (c) 1998-2018 the Tinyproxy authors.
Copyright (c) 2000-2001 Robert James Kaes;
Copyright (c) 2009-2010 Mukund Sivaraman;
Copyright (c) 2009-2010 Michael Adam.
This program is distributed under the terms of the GNU General Public This program is distributed under the terms of the GNU General Public
License version 2 or above. See the COPYING file for additional License version 2 or above. See the COPYING file for additional

View File

@ -12,7 +12,7 @@ tinyproxy - A light-weight HTTP proxy daemon
SYNOPSIS SYNOPSIS
-------- --------
*tinyproxy* [-vldch] *tinyproxy* [-vdch]
DESCRIPTION DESCRIPTION
@ -40,9 +40,6 @@ OPTIONS
*-h*:: *-h*::
Display a short help screen of command line arguments and exit. Display a short help screen of command line arguments and exit.
*-l*::
Display the licensing agreement.
*-v*:: *-v*::
Display version information and exit. Display version information and exit.
@ -153,10 +150,7 @@ This manpage was written by the Tinyproxy project team.
COPYRIGHT COPYRIGHT
--------- ---------
Copyright (c) 1998-2000 Steven Young; Copyright (c) 1998-2018 the Tinyproxy authors.
Copyright (c) 2000-2001 Robert James Kaes;
Copyright (c) 2009-2010 Mukund Sivaraman;
Copyright (c) 2009-2010 Michael Adam.
This program is distributed under the terms of the GNU General Public This program is distributed under the terms of the GNU General Public
License version 2 or above. See the COPYING file for additional License version 2 or above. See the COPYING file for additional

View File

@ -90,7 +90,8 @@ StatFile "@pkgdatadir@/stats.html"
# LogFile: Allows you to specify the location where information should # LogFile: Allows you to specify the location where information should
# be logged to. If you would prefer to log to syslog, then disable this # be logged to. If you would prefer to log to syslog, then disable this
# and enable the Syslog directive. These directives are mutually # and enable the Syslog directive. These directives are mutually
# exclusive. # exclusive. If neither Syslog nor LogFile are specified, output goes
# to stdout.
# #
#LogFile "@localstatedir@/log/tinyproxy/tinyproxy.log" #LogFile "@localstatedir@/log/tinyproxy/tinyproxy.log"
@ -102,7 +103,7 @@ StatFile "@pkgdatadir@/stats.html"
#Syslog On #Syslog On
# #
# LogLevel: # LogLevel: Warning
# #
# Set the logging level. Allowed settings are: # Set the logging level. Allowed settings are:
# Critical (least verbose) # Critical (least verbose)
@ -121,6 +122,7 @@ LogLevel Info
# #
# PidFile: Write the PID of the main tinyproxy thread to this file so it # PidFile: Write the PID of the main tinyproxy thread to this file so it
# can be used for signalling purposes. # can be used for signalling purposes.
# If not specified, no pidfile will be written.
# #
#PidFile "@localstatedir@/run/tinyproxy/tinyproxy.pid" #PidFile "@localstatedir@/run/tinyproxy/tinyproxy.pid"
@ -138,25 +140,37 @@ LogLevel Info
# The upstream rules allow you to selectively route upstream connections # The upstream rules allow you to selectively route upstream connections
# based on the host/domain of the site being accessed. # based on the host/domain of the site being accessed.
# #
# Syntax: upstream type (user:pass@)ip:port ("domain")
# Or: upstream none "domain"
# The parts in parens are optional.
# Possible types are http, socks4, socks5, none
#
# For example: # For example:
# # connection to test domain goes through testproxy # # connection to test domain goes through testproxy
# upstream testproxy:8008 ".test.domain.invalid" # upstream http testproxy:8008 ".test.domain.invalid"
# upstream testproxy:8008 ".our_testbed.example.com" # upstream http testproxy:8008 ".our_testbed.example.com"
# upstream testproxy:8008 "192.168.128.0/255.255.254.0" # upstream http testproxy:8008 "192.168.128.0/255.255.254.0"
#
# # upstream proxy using basic authentication
# upstream http user:pass@testproxy:8008 ".test.domain.invalid"
# #
# # no upstream proxy for internal websites and unqualified hosts # # no upstream proxy for internal websites and unqualified hosts
# no upstream ".internal.example.com" # upstream none ".internal.example.com"
# no upstream "www.example.com" # upstream none "www.example.com"
# no upstream "10.0.0.0/8" # upstream none "10.0.0.0/8"
# no upstream "192.168.0.0/255.255.254.0" # upstream none "192.168.0.0/255.255.254.0"
# no upstream "." # upstream none "."
# #
# # connection to these boxes go through their DMZ firewalls # # connection to these boxes go through their DMZ firewalls
# upstream cust1_firewall:8008 "testbed_for_cust1" # upstream http cust1_firewall:8008 "testbed_for_cust1"
# upstream cust2_firewall:8008 "testbed_for_cust2" # upstream http cust2_firewall:8008 "testbed_for_cust2"
# #
# # default upstream is internet firewall # # default upstream is internet firewall
# upstream firewall.internal.example.com:80 # upstream http firewall.internal.example.com:80
#
# You may also use SOCKS4/SOCKS5 upstream proxies:
# upstream socks4 127.0.0.1:9050
# upstream socks5 socksproxy:1080
# #
# The LAST matching rule wins the route decision. As you can see, you # The LAST matching rule wins the route decision. As you can see, you
# can use a host, or a domain: # can use a host, or a domain:
@ -166,7 +180,7 @@ LogLevel Info
# IP/bits matches network/mask # IP/bits matches network/mask
# IP/mask matches network/mask # IP/mask matches network/mask
# #
#Upstream some.remote.proxy:port #Upstream http some.remote.proxy:port
# #
# MaxClients: This is the absolute highest number of threads which will # MaxClients: This is the absolute highest number of threads which will
@ -209,6 +223,11 @@ MaxRequestsPerChild 0
# #
Allow 127.0.0.1 Allow 127.0.0.1
# BasicAuth: HTTP "Basic Authentication" for accessing the proxy.
# If there are any entries specified, access is only granted for authenticated
# users.
#BasicAuth user password
# #
# AddHeader: Adds the specified headers to outgoing HTTP requests that # AddHeader: Adds the specified headers to outgoing HTTP requests that
# Tinyproxy makes. Note that this option will not work for HTTPS # Tinyproxy makes. Note that this option will not work for HTTPS
@ -292,12 +311,12 @@ ViaProxyName "tinyproxy"
# ConnectPort: This is a list of ports allowed by tinyproxy when the # ConnectPort: This is a list of ports allowed by tinyproxy when the
# CONNECT method is used. To disable the CONNECT method altogether, set # CONNECT method is used. To disable the CONNECT method altogether, set
# the value to 0. If no ConnectPort line is found, all ports are # the value to 0. If no ConnectPort line is found, all ports are
# allowed (which is not very secure.) # allowed.
# #
# The following two ports are used by SSL. # The following two ports are used by SSL.
# #
ConnectPort 443 #ConnectPort 443
ConnectPort 563 #ConnectPort 563
# #
# Configure one or more ReversePath directives to enable reverse proxy # Configure one or more ReversePath directives to enable reverse proxy

2
scripts/Makefile.am Normal file
View File

@ -0,0 +1,2 @@
EXTRA_DIST = \
version.sh

10
scripts/gen-authors.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)"
BASE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
AUTHORS_FILE="${BASE_DIR}/AUTHORS"
type git > /dev/null || exit
test -d "${BASE_DIR}/.git" || exit
git log --all --format='%aN' | sort -u > "${AUTHORS_FILE}"

15
scripts/version.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/sh
SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)"
GIT_DIR="${SCRIPT_DIR}/../.git"
if test -d "${GIT_DIR}" ; then
if type git >/dev/null 2>&1 ; then
git describe --match '[0-9]*.[0-9]*.[0-9]*' 2>/dev/null \
| sed -e 's/-/-git-/'
else
sed 's/$/-git/' < VERSION
fi
else
cat VERSION
fi

View File

@ -17,7 +17,7 @@
pkgsysconfdir = $(sysconfdir)/$(PACKAGE) pkgsysconfdir = $(sysconfdir)/$(PACKAGE)
sbin_PROGRAMS = tinyproxy bin_PROGRAMS = tinyproxy
AM_CPPFLAGS = \ AM_CPPFLAGS = \
-DSYSCONFDIR=\"${pkgsysconfdir}\" \ -DSYSCONFDIR=\"${pkgsysconfdir}\" \
@ -26,7 +26,6 @@ AM_CPPFLAGS = \
tinyproxy_SOURCES = \ tinyproxy_SOURCES = \
acl.c acl.h \ acl.c acl.h \
anonymous.c anonymous.h \ anonymous.c anonymous.h \
authors.c authors.h \
buffer.c buffer.h \ buffer.c buffer.h \
child.c child.h \ child.c child.h \
common.h \ common.h \
@ -47,6 +46,8 @@ tinyproxy_SOURCES = \
utils.c utils.h \ utils.c utils.h \
vector.c vector.h \ vector.c vector.h \
upstream.c upstream.h \ upstream.c upstream.h \
basicauth.c basicauth.h \
base64.c base64.h \
connect-ports.c connect-ports.h connect-ports.c connect-ports.h
EXTRA_tinyproxy_SOURCES = filter.c filter.h \ EXTRA_tinyproxy_SOURCES = filter.c filter.h \
@ -54,16 +55,3 @@ EXTRA_tinyproxy_SOURCES = filter.c filter.h \
transparent-proxy.c transparent-proxy.h transparent-proxy.c transparent-proxy.h
tinyproxy_DEPENDENCIES = @ADDITIONAL_OBJECTS@ tinyproxy_DEPENDENCIES = @ADDITIONAL_OBJECTS@
tinyproxy_LDADD = @ADDITIONAL_OBJECTS@ tinyproxy_LDADD = @ADDITIONAL_OBJECTS@
EXTRA_DIST = \
authors.xsl
authors.c: $(top_srcdir)/authors.xml $(srcdir)/authors.xsl
if HAVE_XSLTPROC
$(AM_V_GEN) $(XSLTPROC) $(srcdir)/authors.xsl $< > $(@) || rm -f $(@)
else
@echo "*** xsltproc is required to regenerate $(@) ***"; exit 1;
endif
BUILT_SOURCES = \
authors.c

View File

@ -1,50 +0,0 @@
/* NOTE: This file is auto-generated from authors.xml, do not edit it. */
#include "authors.h"
static const char * const authors[] =
{
"Andrew Stribblehill",
"Chris Lightfoot",
"Daniel Egger",
"David Shanks",
"Dmitry Semyonov",
"George Talusan",
"James E. Flemer",
"Jeremy Hinegardner",
"John van der Kamp",
"Jordi Mallach",
"Kim Holviala",
"Mathew Mrosko",
"Matthew Dempsky",
"Michael Adam",
"Moritz Muehlenhoff",
"Mukund Sivaraman",
"Petr Lampa",
"Robert James Kaes",
"Steven Young",
NULL
};
static const char * const documenters[] =
{
"Marc Silver",
"Michael Adam",
"Mukund Sivaraman",
"Robert James Kaes",
"Steven Young",
NULL
};
const char * const *
authors_get_authors (void)
{
return authors;
}
const char * const *
authors_get_documenters (void)
{
return documenters;
}

View File

@ -1,64 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Simple XSL transformation to create a header file from
authors.xml. This file was adapted from GIMP.
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<xsl:output method="text" />
<xsl:template name="recent-contributor">
<xsl:param name="role" />
<xsl:apply-templates select="dc:contributor[contains(@role, $role)]" />
</xsl:template>
<xsl:template match="/dc:authors">
<xsl:text>
/* NOTE: This file is auto-generated from authors.xml, do not edit it. */
#include "authors.h"
static const char * const authors[] =
{
</xsl:text>
<xsl:call-template name="recent-contributor">
<xsl:with-param name="role" select="'author'"/>
</xsl:call-template>
<xsl:text> NULL
};
</xsl:text>
<xsl:text>
static const char * const documenters[] =
{
</xsl:text>
<xsl:call-template name="recent-contributor">
<xsl:with-param name="role" select="'documenter'"/>
</xsl:call-template>
<xsl:text> NULL
};
const char * const *
authors_get_authors (void)
{
return authors;
}
const char * const *
authors_get_documenters (void)
{
return documenters;
}
</xsl:text>
</xsl:template>
<xsl:template match="dc:contributor"> "<xsl:apply-templates />",
</xsl:template>
</xsl:stylesheet>

57
src/base64.c Normal file
View File

@ -0,0 +1,57 @@
/* tinyproxy - A fast light-weight HTTP proxy
* this file Copyright (C) 2016-2018 rofl0r
*
* 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 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "base64.h"
static const char base64_tbl[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*
rofl0r's base64 impl (taken from libulz)
takes count bytes from src, writing base64 encoded string into dst.
dst needs to be at least BASE64ENC_BYTES(count) + 1 bytes in size.
the string in dst will be zero-terminated.
*/
void base64enc(char *dst, const void* src, size_t count)
{
unsigned const char *s = src;
char* d = dst;
while(count) {
int i = 0, n = *s << 16;
s++;
count--;
if(count) {
n |= *s << 8;
s++;
count--;
i++;
}
if(count) {
n |= *s;
s++;
count--;
i++;
}
*d++ = base64_tbl[(n >> 18) & 0x3f];
*d++ = base64_tbl[(n >> 12) & 0x3f];
*d++ = i ? base64_tbl[(n >> 6) & 0x3f] : '=';
*d++ = i == 2 ? base64_tbl[n & 0x3f] : '=';
}
*d = 0;
}

View File

@ -1,5 +1,5 @@
/* tinyproxy - A fast light-weight HTTP proxy /* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2010 Mukund Sivaraman <muks@banu.com> * this file Copyright (C) 2016-2018 rofl0r
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -16,15 +16,14 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifndef __AUTHORS_H__ #ifndef TINYPROXY_BASE64_H
#define __AUTHORS_H__ #define TINYPROXY_BASE64_H
#include "common.h" #include <stddef.h>
const char * const * /* calculates number of bytes base64-encoded stream of N bytes will take. */
authors_get_authors (void); #define BASE64ENC_BYTES(N) (((N+2)/3)*4)
void base64enc(char *dst, const void* src, size_t count);
const char * const * #endif
authors_get_documenters (void);
#endif /* __AUTHORS_H__ */

98
src/basicauth.c Normal file
View File

@ -0,0 +1,98 @@
/* tinyproxy - A fast light-weight HTTP proxy
* This file: Copyright (C) 2016-2017 rofl0r
*
* 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 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "main.h"
#include "basicauth.h"
#include "conns.h"
#include "heap.h"
#include "html-error.h"
#include "log.h"
#include "conf.h"
#include "base64.h"
/*
* Create basic-auth token in buf.
* Returns strlen of token on success,
* -1 if user/pass missing
* 0 if user/pass too long
*/
ssize_t basicauth_string(const char *user, const char *pass,
char *buf, size_t bufsize)
{
char tmp[256+2];
int l;
if (!user || !pass) return -1;
l = snprintf(tmp, sizeof tmp, "%s:%s", user, pass);
if (l < 0 || l >= (ssize_t) sizeof tmp) return 0;
if (bufsize < (BASE64ENC_BYTES((unsigned)l) + 1)) return 0;
base64enc(buf, tmp, l);
return BASE64ENC_BYTES(l);
}
/*
* Add entry to the basicauth list
*/
void basicauth_add (vector_t authlist,
const char *user, const char *pass)
{
char b[BASE64ENC_BYTES((256+2)-1) + 1];
ssize_t ret;
ret = basicauth_string(user, pass, b, sizeof b);
if (ret == -1) {
log_message (LOG_WARNING,
"Illegal basicauth rule: missing user or pass");
return;
} else if (ret == 0) {
log_message (LOG_WARNING,
"User / pass in basicauth rule too long");
return;
}
if (vector_append(authlist, b, ret + 1) == -ENOMEM) {
log_message (LOG_ERR,
"Unable to allocate memory in basicauth_add()");
return;
}
log_message (LOG_INFO,
"Added basic auth user : %s", user);
}
/*
* Check if a user/password combination (encoded as base64)
* is in the basicauth list.
* return 1 on success, 0 on failure.
*/
int basicauth_check (vector_t authlist, const char *authstring)
{
ssize_t vl, i;
size_t el;
const char* entry;
vl = vector_length (authlist);
if (vl == -EINVAL) return 0;
for (i = 0; i < vl; i++) {
entry = vector_getentry (authlist, i, &el);
if (strcmp (authstring, entry) == 0)
return 1;
}
return 0;
}

35
src/basicauth.h Normal file
View File

@ -0,0 +1,35 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2005 Robert James Kaes <rjkaes@users.sourceforge.net>
*
* 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 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* See 'basicauth.c' for detailed information. */
#ifndef TINYPROXY_BASICAUTH_H
#define TINYPROXY_BASICAUTH_H
#include <stddef.h>
#include "vector.h"
extern ssize_t basicauth_string(const char *user, const char *pass,
char *buf, size_t bufsize);
extern void basicauth_add (vector_t authlist,
const char *user, const char *pass);
extern int basicauth_check (vector_t authlist, const char *authstring);
#endif

View File

@ -36,6 +36,7 @@
#include "reverse-proxy.h" #include "reverse-proxy.h"
#include "upstream.h" #include "upstream.h"
#include "connect-ports.h" #include "connect-ports.h"
#include "basicauth.h"
/* /*
* The configuration directives are defined in the structure below. Each * The configuration directives are defined in the structure below. Each
@ -116,6 +117,7 @@ static HANDLE_FUNC (handle_nop)
} /* do nothing function */ } /* do nothing function */
static HANDLE_FUNC (handle_allow); static HANDLE_FUNC (handle_allow);
static HANDLE_FUNC (handle_basicauth);
static HANDLE_FUNC (handle_anonymous); static HANDLE_FUNC (handle_anonymous);
static HANDLE_FUNC (handle_bind); static HANDLE_FUNC (handle_bind);
static HANDLE_FUNC (handle_bindsame); static HANDLE_FUNC (handle_bindsame);
@ -232,6 +234,7 @@ struct {
handle_deny), handle_deny),
STDCONF ("bind", "(" IP "|" IPV6 ")", handle_bind), STDCONF ("bind", "(" IP "|" IPV6 ")", handle_bind),
/* other */ /* other */
STDCONF ("basicauth", ALNUM WS ALNUM, handle_basicauth),
STDCONF ("errorfile", INT WS STR, handle_errorfile), STDCONF ("errorfile", INT WS STR, handle_errorfile),
STDCONF ("addheader", STR WS STR, handle_addheader), STDCONF ("addheader", STR WS STR, handle_addheader),
@ -251,13 +254,15 @@ struct {
STDCONF ("reversepath", STR "(" WS STR ")?", handle_reversepath), STDCONF ("reversepath", STR "(" WS STR ")?", handle_reversepath),
#endif #endif
#ifdef UPSTREAM_SUPPORT #ifdef UPSTREAM_SUPPORT
/* upstream is rather complicated */
{ {
BEGIN "(no" WS "upstream)" WS STR END, handle_upstream_no, NULL BEGIN "(upstream)" WS "(none)" WS STR END, handle_upstream_no, NULL
}, },
{ {
BEGIN "(upstream)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR BEGIN "(upstream)" WS "(http|socks4|socks5)" WS
")?" END, handle_upstream, NULL "(" ALNUM /*username*/ ":" ALNUM /*password*/ "@" ")?"
"(" IP "|" ALNUM ")"
":" INT "(" WS STR ")?"
END, handle_upstream, NULL
}, },
#endif #endif
/* loglevel */ /* loglevel */
@ -291,6 +296,7 @@ static void free_config (struct config_s *conf)
safefree (conf->user); safefree (conf->user);
safefree (conf->group); safefree (conf->group);
vector_delete(conf->listen_addrs); vector_delete(conf->listen_addrs);
vector_delete(conf->basicauth_list);
#ifdef FILTER_ENABLE #ifdef FILTER_ENABLE
safefree (conf->filter); safefree (conf->filter);
#endif /* FILTER_ENABLE */ #endif /* FILTER_ENABLE */
@ -786,12 +792,7 @@ static HANDLE_FUNC (handle_xtinyproxy)
static HANDLE_FUNC (handle_syslog) static HANDLE_FUNC (handle_syslog)
{ {
#ifdef HAVE_SYSLOG_H
return set_bool_arg (&conf->syslog, line, &match[2]); return set_bool_arg (&conf->syslog, line, &match[2]);
#else
fprintf (stderr, "Syslog support not compiled in executable.\n");
return 1;
#endif
} }
static HANDLE_FUNC (handle_bindsame) static HANDLE_FUNC (handle_bindsame)
@ -892,7 +893,6 @@ static HANDLE_FUNC (handle_deny)
static HANDLE_FUNC (handle_bind) static HANDLE_FUNC (handle_bind)
{ {
#ifndef TRANSPARENT_PROXY
int r = set_string_arg (&conf->bind_address, line, &match[2]); int r = set_string_arg (&conf->bind_address, line, &match[2]);
if (r) if (r)
@ -900,11 +900,6 @@ static HANDLE_FUNC (handle_bind)
log_message (LOG_INFO, log_message (LOG_INFO,
"Outgoing connections bound to IP %s", conf->bind_address); "Outgoing connections bound to IP %s", conf->bind_address);
return 0; return 0;
#else
fprintf (stderr,
"\"Bind\" cannot be used with transparent support enabled.\n");
return 1;
#endif
} }
static HANDLE_FUNC (handle_listen) static HANDLE_FUNC (handle_listen)
@ -1011,6 +1006,27 @@ static HANDLE_FUNC (handle_loglevel)
return -1; return -1;
} }
static HANDLE_FUNC (handle_basicauth)
{
char *user, *pass;
user = get_string_arg(line, &match[2]);
if (!user)
return -1;
pass = get_string_arg(line, &match[3]);
if (!pass) {
safefree (user);
return -1;
}
if (!conf->basicauth_list) {
conf->basicauth_list = vector_create ();
}
basicauth_add (conf->basicauth_list, user, pass);
safefree (user);
safefree (pass);
return 0;
}
#ifdef FILTER_ENABLE #ifdef FILTER_ENABLE
static HANDLE_FUNC (handle_filter) static HANDLE_FUNC (handle_filter)
{ {
@ -1087,27 +1103,58 @@ static HANDLE_FUNC (handle_reversepath)
#endif #endif
#ifdef UPSTREAM_SUPPORT #ifdef UPSTREAM_SUPPORT
static enum proxy_type pt_from_string(const char *s)
{
static const char pt_map[][7] = {
[PT_NONE] = "none",
[PT_HTTP] = "http",
[PT_SOCKS4] = "socks4",
[PT_SOCKS5] = "socks5",
};
unsigned i;
for (i = 0; i < sizeof(pt_map)/sizeof(pt_map[0]); i++)
if (!strcmp(pt_map[i], s))
return i;
return PT_NONE;
}
static HANDLE_FUNC (handle_upstream) static HANDLE_FUNC (handle_upstream)
{ {
char *ip; char *ip;
int port; int port, mi = 2;
char *domain; char *domain = 0, *user = 0, *pass = 0, *tmp;
enum proxy_type pt;
ip = get_string_arg (line, &match[2]); tmp = get_string_arg (line, &match[mi]);
pt = pt_from_string(tmp);
safefree(tmp);
mi += 2;
if (match[mi].rm_so != -1)
user = get_string_arg (line, &match[mi]);
mi++;
if (match[mi].rm_so != -1)
pass = get_string_arg (line, &match[mi]);
mi++;
ip = get_string_arg (line, &match[mi]);
if (!ip) if (!ip)
return -1; return -1;
port = (int) get_long_arg (line, &match[7]); mi += 5;
if (match[10].rm_so != -1) { port = (int) get_long_arg (line, &match[mi]);
domain = get_string_arg (line, &match[10]); mi += 3;
if (domain) {
upstream_add (ip, port, domain, &conf->upstream_list);
safefree (domain);
}
} else {
upstream_add (ip, port, NULL, &conf->upstream_list);
}
if (match[mi].rm_so != -1)
domain = get_string_arg (line, &match[mi]);
upstream_add (ip, port, domain, user, pass, pt, &conf->upstream_list);
safefree (user);
safefree (pass);
safefree (domain);
safefree (ip); safefree (ip);
return 0; return 0;
@ -1117,11 +1164,11 @@ static HANDLE_FUNC (handle_upstream_no)
{ {
char *domain; char *domain;
domain = get_string_arg (line, &match[2]); domain = get_string_arg (line, &match[3]);
if (!domain) if (!domain)
return -1; return -1;
upstream_add (NULL, 0, domain, &conf->upstream_list); upstream_add (NULL, 0, domain, 0, 0, PT_NONE, &conf->upstream_list);
safefree (domain); safefree (domain);
return 0; return 0;

View File

@ -37,6 +37,7 @@ typedef struct {
* Hold all the configuration time information. * Hold all the configuration time information.
*/ */
struct config_s { struct config_s {
vector_t basicauth_list;
char *logf_name; char *logf_name;
char *config_file; char *config_file;
unsigned int syslog; /* boolean */ unsigned int syslog; /* boolean */

View File

@ -132,6 +132,7 @@ send_html_file (FILE *infile, struct conn_s *connptr)
} else } else
in_variable = 0; in_variable = 0;
/* FALL THROUGH */
default: default:
if (!in_variable) { if (!in_variable) {
r = write_message (connptr->client_fd, r = write_message (connptr->client_fd,
@ -156,13 +157,24 @@ send_html_file (FILE *infile, struct conn_s *connptr)
int send_http_headers (struct conn_s *connptr, int code, const char *message) int send_http_headers (struct conn_s *connptr, int code, const char *message)
{ {
const char *headers = const char headers[] =
"HTTP/1.0 %d %s\r\n" "HTTP/1.0 %d %s\r\n"
"Server: %s/%s\r\n" "Server: %s/%s\r\n"
"Content-Type: text/html\r\n" "Connection: close\r\n" "\r\n"; "Content-Type: text/html\r\n"
"%s"
"Connection: close\r\n" "\r\n";
const char auth_str[] =
"Proxy-Authenticate: Basic realm=\""
PACKAGE_NAME "\"\r\n";
/* according to rfc7235, the 407 error must be accompanied by
a Proxy-Authenticate header field. */
const char *add = code == 407 ? auth_str : "";
return (write_message (connptr->client_fd, headers, return (write_message (connptr->client_fd, headers,
code, message, PACKAGE, VERSION)); code, message, PACKAGE, VERSION,
add));
} }
/* /*

View File

@ -70,7 +70,14 @@ static unsigned int logging_initialized = FALSE; /* boolean */
*/ */
int open_log_file (const char *log_file_name) int open_log_file (const char *log_file_name)
{ {
log_file_fd = create_file_safely (log_file_name, FALSE); if (log_file_name == NULL) {
if(config.godaemon == FALSE)
log_file_fd = fileno(stdout);
else
log_file_fd = -1;
} else {
log_file_fd = create_file_safely (log_file_name, FALSE);
}
return log_file_fd; return log_file_fd;
} }
@ -79,7 +86,7 @@ int open_log_file (const char *log_file_name)
*/ */
void close_log_file (void) void close_log_file (void)
{ {
if (log_file_fd < 0) { if (log_file_fd < 0 || log_file_fd == fileno(stdout)) {
return; return;
} }
@ -154,6 +161,9 @@ void log_message (int level, const char *fmt, ...)
goto out; goto out;
} }
if(!config.syslog && log_file_fd == -1)
goto out;
if (config.syslog) { if (config.syslog) {
#ifdef HAVE_VSYSLOG_H #ifdef HAVE_VSYSLOG_H
vsyslog (level, fmt, args); vsyslog (level, fmt, args);
@ -207,7 +217,7 @@ out:
/* /*
* This needs to send any stored log messages. * This needs to send any stored log messages.
*/ */
void send_stored_logs (void) static void send_stored_logs (void)
{ {
char *string; char *string;
char *ptr; char *ptr;

View File

@ -106,7 +106,6 @@ extern void close_log_file (void);
extern void log_message (int level, const char *fmt, ...); extern void log_message (int level, const char *fmt, ...);
extern void set_log_level (int level); extern void set_log_level (int level);
extern void send_stored_logs (void);
extern int setup_logging (void); extern int setup_logging (void);
extern void shutdown_logging (void); extern void shutdown_logging (void);

View File

@ -32,7 +32,6 @@
#include "main.h" #include "main.h"
#include "anonymous.h" #include "anonymous.h"
#include "authors.h"
#include "buffer.h" #include "buffer.h"
#include "conf.h" #include "conf.h"
#include "daemon.h" #include "daemon.h"
@ -87,55 +86,6 @@ display_version (void)
printf ("%s %s\n", PACKAGE, VERSION); printf ("%s %s\n", PACKAGE, VERSION);
} }
/*
* Display the copyright and license for this program.
*/
static void
display_license (void)
{
const char * const *authors;
const char * const *documenters;
display_version ();
printf ("\
\n\
Copyright 1998 Steven Young (sdyoung@well.com)\n\
Copyright 1998-2002 Robert James Kaes (rjkaes@users.sourceforge.net)\n\
Copyright 1999 George Talusan (gstalusan@uwaterloo.ca)\n\
Copyright 2000 Chris Lightfoot (chris@ex-parrot.com)\n\
Copyright 2009-2010 Mukund Sivaraman (muks@banu.com)\n\
Copyright 2009-2010 Michael Adam (obnox@samba.org)\n\
\n\
This program is free software; you can redistribute it and/or modify\n\
it under the terms of the GNU General Public License as published by\n\
the Free Software Foundation; either version 2, or (at your option)\n\
any later version.\n\
\n\
This program is distributed in the hope that it will be useful,\n\
but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
GNU General Public License for more details.\n\
\n\
You should have received a copy of the GNU General Public License\n\
along with this program; if not, write to the Free Software\n\
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.\n\
\n");
printf ("\nAUTHORS:\n");
for (authors = authors_get_authors (); *authors; authors++) {
printf (" %s\n", *authors);
}
printf ("\nDOCUMENTERS:\n");
for (documenters = authors_get_documenters ();
*documenters; documenters++) {
printf (" %s\n", *documenters);
}
printf ("\n");
}
/* /*
* Display usage to the user. * Display usage to the user.
*/ */
@ -150,7 +100,6 @@ display_usage (void)
" -d Do not daemonize (run in foreground).\n" " -d Do not daemonize (run in foreground).\n"
" -c FILE Use an alternate configuration file.\n" " -c FILE Use an alternate configuration file.\n"
" -h Display this usage information.\n" " -h Display this usage information.\n"
" -l Display the license.\n"
" -v Display version information.\n"); " -v Display version information.\n");
/* Display the modes compiled into tinyproxy */ /* Display the modes compiled into tinyproxy */
@ -224,16 +173,12 @@ process_cmdline (int argc, char **argv, struct config_s *conf)
{ {
int opt; int opt;
while ((opt = getopt (argc, argv, "c:vldh")) != EOF) { while ((opt = getopt (argc, argv, "c:vdh")) != EOF) {
switch (opt) { switch (opt) {
case 'v': case 'v':
display_version (); display_version ();
exit (EX_OK); exit (EX_OK);
case 'l':
display_license ();
exit (EX_OK);
case 'd': case 'd':
conf->godaemon = FALSE; conf->godaemon = FALSE;
break; break;
@ -355,8 +300,8 @@ static void initialize_config_defaults (struct config_s *conf)
conf->errorpages = NULL; conf->errorpages = NULL;
conf->stathost = safestrdup (TINYPROXY_STATHOST); conf->stathost = safestrdup (TINYPROXY_STATHOST);
conf->idletimeout = MAX_IDLE_TIME; conf->idletimeout = MAX_IDLE_TIME;
conf->logf_name = safestrdup (LOCALSTATEDIR "/log/tinyproxy/tinyproxy.log"); conf->logf_name = NULL;
conf->pidpath = safestrdup (LOCALSTATEDIR "/run/tinyproxy/tinyproxy.pid"); conf->pidpath = NULL;
} }
/** /**
@ -415,8 +360,13 @@ main (int argc, char **argv)
anonymous_insert ("Content-Type"); anonymous_insert ("Content-Type");
} }
if (config.godaemon == TRUE) if (config.godaemon == TRUE) {
if (!config.syslog && config.logf_name == NULL)
fprintf(stderr, "WARNING: logging deactivated "
"(can't log to stdout when daemonized)\n");
makedaemon (); makedaemon ();
}
if (set_signal_handler (SIGPIPE, SIG_IGN) == SIG_ERR) { if (set_signal_handler (SIGPIPE, SIG_IGN) == SIG_ERR) {
fprintf (stderr, "%s: Could not set the \"SIGPIPE\" signal.\n", fprintf (stderr, "%s: Could not set the \"SIGPIPE\" signal.\n",
@ -436,6 +386,15 @@ main (int argc, char **argv)
exit (EX_OSERR); exit (EX_OSERR);
} }
/* Create pid file before we drop privileges */
if (config.pidpath) {
if (pidfile_create (config.pidpath) < 0) {
fprintf (stderr, "%s: Could not create PID file.\n",
argv[0]);
exit (EX_OSERR);
}
}
/* Switch to a different user if we're running as root */ /* Switch to a different user if we're running as root */
if (geteuid () == 0) if (geteuid () == 0)
change_user (argv[0]); change_user (argv[0]);
@ -448,15 +407,6 @@ main (int argc, char **argv)
exit (EX_SOFTWARE); exit (EX_SOFTWARE);
} }
/* Create pid file after we drop privileges */
if (config.pidpath) {
if (pidfile_create (config.pidpath) < 0) {
fprintf (stderr, "%s: Could not create PID file.\n",
argv[0]);
exit (EX_OSERR);
}
}
if (child_pool_create () < 0) { if (child_pool_create () < 0) {
fprintf (stderr, fprintf (stderr,
"%s: Could not create the pool of children.\n", "%s: Could not create the pool of children.\n",
@ -496,7 +446,7 @@ main (int argc, char **argv)
child_close_sock (); child_close_sock ();
/* Remove the PID file */ /* Remove the PID file */
if (unlink (config.pidpath) < 0) { if (config.pidpath != NULL && unlink (config.pidpath) < 0) {
log_message (LOG_WARNING, log_message (LOG_WARNING,
"Could not remove PID file \"%s\": %s.", "Could not remove PID file \"%s\": %s.",
config.pidpath, strerror (errno)); config.pidpath, strerror (errno));

View File

@ -32,10 +32,11 @@
* Write the buffer to the socket. If an EINTR occurs, pick up and try * Write the buffer to the socket. If an EINTR occurs, pick up and try
* again. Keep sending until the buffer has been sent. * again. Keep sending until the buffer has been sent.
*/ */
ssize_t safe_write (int fd, const char *buffer, size_t count) ssize_t safe_write (int fd, const void *buf, size_t count)
{ {
ssize_t len; ssize_t len;
size_t bytestosend; size_t bytestosend;
const char *buffer = buf;
assert (fd >= 0); assert (fd >= 0);
assert (buffer != NULL); assert (buffer != NULL);
@ -67,7 +68,7 @@ ssize_t safe_write (int fd, const char *buffer, size_t count)
* Matched pair for safe_write(). If an EINTR occurs, pick up and try * Matched pair for safe_write(). If an EINTR occurs, pick up and try
* again. * again.
*/ */
ssize_t safe_read (int fd, char *buffer, size_t count) ssize_t safe_read (int fd, void *buffer, size_t count)
{ {
ssize_t len; ssize_t len;

View File

@ -21,8 +21,8 @@
#ifndef TINYPROXY_NETWORK_H #ifndef TINYPROXY_NETWORK_H
#define TINYPROXY_NETWORK_H #define TINYPROXY_NETWORK_H
extern ssize_t safe_write (int fd, const char *buffer, size_t count); extern ssize_t safe_write (int fd, const void *buf, size_t count);
extern ssize_t safe_read (int fd, char *buffer, size_t count); extern ssize_t safe_read (int fd, void *buf, size_t count);
extern int write_message (int fd, const char *fmt, ...); extern int write_message (int fd, const char *fmt, ...);
extern ssize_t readline (int fd, char **whole_buffer); extern ssize_t readline (int fd, char **whole_buffer);

View File

@ -48,6 +48,7 @@
#include "upstream.h" #include "upstream.h"
#include "connect-ports.h" #include "connect-ports.h"
#include "conf.h" #include "conf.h"
#include "basicauth.h"
/* /*
* Maximum length of a HTTP line * Maximum length of a HTTP line
@ -61,9 +62,11 @@
#ifdef UPSTREAM_SUPPORT #ifdef UPSTREAM_SUPPORT
# define UPSTREAM_CONFIGURED() (config.upstream_list != NULL) # define UPSTREAM_CONFIGURED() (config.upstream_list != NULL)
# define UPSTREAM_HOST(host) upstream_get(host, config.upstream_list) # define UPSTREAM_HOST(host) upstream_get(host, config.upstream_list)
# define UPSTREAM_IS_HTTP(conn) (conn->upstream_proxy != NULL && conn->upstream_proxy->type == PT_HTTP)
#else #else
# define UPSTREAM_CONFIGURED() (0) # define UPSTREAM_CONFIGURED() (0)
# define UPSTREAM_HOST(host) (NULL) # define UPSTREAM_HOST(host) (NULL)
# define UPSTREAM_IS_HTTP(up) (0)
#endif #endif
/* /*
@ -267,6 +270,17 @@ establish_http_connection (struct conn_s *connptr, struct request_s *request)
"Connection: close\r\n", "Connection: close\r\n",
request->method, request->path, request->method, request->path,
request->host, portbuff); request->host, portbuff);
} else if (connptr->upstream_proxy &&
connptr->upstream_proxy->type == PT_HTTP &&
connptr->upstream_proxy->ua.authstr) {
return write_message (connptr->server_fd,
"%s %s HTTP/1.0\r\n"
"Host: %s%s\r\n"
"Connection: close\r\n"
"Proxy-Authorization: Basic %s\r\n",
request->method, request->path,
request->host, portbuff,
connptr->upstream_proxy->ua.authstr);
} else { } else {
return write_message (connptr->server_fd, return write_message (connptr->server_fd,
"%s %s HTTP/1.0\r\n" "%s %s HTTP/1.0\r\n"
@ -882,10 +896,10 @@ process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders)
/* /*
* Don't send headers if there's already an error, if the request was * Don't send headers if there's already an error, if the request was
* a stats request, or if this was a CONNECT method (unless upstream * a stats request, or if this was a CONNECT method (unless upstream
* proxy is in use.) * http proxy is in use.)
*/ */
if (connptr->server_fd == -1 || connptr->show_stats if (connptr->server_fd == -1 || connptr->show_stats
|| (connptr->connect_method && (connptr->upstream_proxy == NULL))) { || (connptr->connect_method && ! UPSTREAM_IS_HTTP(connptr))) {
log_message (LOG_INFO, log_message (LOG_INFO,
"Not sending client headers to remote machine"); "Not sending client headers to remote machine");
return 0; return 0;
@ -1317,6 +1331,122 @@ static void relay_connection (struct conn_s *connptr)
return; return;
} }
static int
connect_to_upstream_proxy(struct conn_s *connptr, struct request_s *request)
{
unsigned len;
unsigned char buff[512]; /* won't use more than 7 + 255 */
unsigned short port;
size_t ulen, passlen;
struct hostent *host;
struct upstream *cur_upstream = connptr->upstream_proxy;
ulen = cur_upstream->ua.user ? strlen(cur_upstream->ua.user) : 0;
passlen = cur_upstream->pass ? strlen(cur_upstream->pass) : 0;
log_message(LOG_CONN,
"Established connection to %s proxy \"%s\" using file descriptor %d.",
proxy_type_name(cur_upstream->type), cur_upstream->host, connptr->server_fd);
if (cur_upstream->type == PT_SOCKS4) {
buff[0] = 4; /* socks version */
buff[1] = 1; /* connect command */
port = htons(request->port);
memcpy(&buff[2], &port, 2); /* dest port */
host = gethostbyname(request->host);
memcpy(&buff[4], host->h_addr_list[0], 4); /* dest ip */
buff[8] = 0; /* user */
if (9 != safe_write(connptr->server_fd, buff, 9))
return -1;
if (8 != safe_read(connptr->server_fd, buff, 8))
return -1;
if (buff[0]!=0 || buff[1]!=90)
return -1;
} else if (cur_upstream->type == PT_SOCKS5) {
/* init */
int n_methods = ulen ? 2 : 1;
buff[0] = 5; /* socks version */
buff[1] = n_methods; /* number of methods */
buff[2] = 0; /* no auth method */
if (ulen) buff[3] = 2; /* auth method -> username / password */
if (2+n_methods != safe_write(connptr->server_fd, buff, 2+n_methods))
return -1;
if (2 != safe_read(connptr->server_fd, buff, 2))
return -1;
if (buff[0] != 5 || (buff[1] != 0 && buff[1] != 2))
return -1;
if (buff[1] == 2) {
/* authentication */
char in[2];
char out[515];
char *cur = out;
size_t c;
*cur++ = 1; /* version */
c = ulen & 0xFF;
*cur++ = c;
memcpy(cur, cur_upstream->ua.user, c);
cur += c;
c = passlen & 0xFF;
*cur++ = c;
memcpy(cur, cur_upstream->pass, c);
cur += c;
if((cur - out) != safe_write(connptr->server_fd, out, cur - out))
return -1;
if(2 != safe_read(connptr->server_fd, in, 2))
return -1;
if(in[1] != 0 || !(in[0] == 5 || in[0] == 1)) {
return -1;
}
}
/* connect */
buff[0] = 5; /* socks version */
buff[1] = 1; /* connect */
buff[2] = 0; /* reserved */
buff[3] = 3; /* domainname */
len=strlen(request->host);
if(len>255)
return -1;
buff[4] = len; /* length of domainname */
memcpy(&buff[5], request->host, len); /* dest ip */
port = htons(request->port);
memcpy(&buff[5+len], &port, 2); /* dest port */
if (7+len != safe_write(connptr->server_fd, buff, 7+len))
return -1;
if (4 != safe_read(connptr->server_fd, buff, 4))
return -1;
if (buff[0]!=5 || buff[1]!=0)
return -1;
switch(buff[3]) {
case 1: len=4; break; /* ip v4 */
case 4: len=16; break; /* ip v6 */
case 3: /* domainname */
if (1 != safe_read(connptr->server_fd, buff, 1))
return -1;
len = buff[0]; /* max = 255 */
break;
default: return -1;
}
if (2+len != safe_read(connptr->server_fd, buff, 2+len))
return -1;
} else {
return -1;
}
if (connptr->connect_method)
return 0;
return establish_http_connection(connptr, request);
}
/* /*
* Establish a connection to the upstream proxy server. * Establish a connection to the upstream proxy server.
*/ */
@ -1360,6 +1490,9 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request)
return -1; return -1;
} }
if (cur_upstream->type != PT_HTTP)
return connect_to_upstream_proxy(connptr, request);
log_message (LOG_CONN, log_message (LOG_CONN,
"Established connection to upstream proxy \"%s\" " "Established connection to upstream proxy \"%s\" "
"using file descriptor %d.", "using file descriptor %d.",
@ -1527,6 +1660,38 @@ void handle_connection (int fd)
goto fail; goto fail;
} }
if (config.basicauth_list != NULL) {
ssize_t len;
char *authstring;
int failure = 1;
len = hashmap_entry_by_key (hashofheaders, "proxy-authorization",
(void **) &authstring);
if (len == 0) {
update_stats (STAT_DENIED);
indicate_http_error (connptr, 407, "Proxy Authentication Required",
"detail",
"This proxy requires authentication.",
NULL);
goto fail;
}
if ( /* currently only "basic" auth supported */
(strncmp(authstring, "Basic ", 6) == 0 ||
strncmp(authstring, "basic ", 6) == 0) &&
basicauth_check (config.basicauth_list, authstring + 6) == 1)
failure = 0;
if(failure) {
update_stats (STAT_DENIED);
indicate_http_error (connptr, 401, "Unauthorized",
"detail",
"The administrator of this proxy has not configured "
"it to service requests from you.",
NULL);
goto fail;
}
hashmap_remove (hashofheaders, "proxy-authorization");
}
/* /*
* Add any user-specified headers (AddHeader directive) to the * Add any user-specified headers (AddHeader directive) to the
* outgoing HTTP request. * outgoing HTTP request.
@ -1579,7 +1744,7 @@ void handle_connection (int fd)
goto fail; goto fail;
} }
if (!(connptr->connect_method && (connptr->upstream_proxy == NULL))) { if (!connptr->connect_method || UPSTREAM_IS_HTTP(connptr)) {
if (process_server_headers (connptr) < 0) { if (process_server_headers (connptr) < 0) {
update_stats (STAT_BADCONN); update_stats (STAT_BADCONN);
goto fail; goto fail;

View File

@ -45,7 +45,7 @@ static int build_url (char **url, const char *host, int port, const char *path)
assert (path != NULL); assert (path != NULL);
len = strlen (host) + strlen (path) + 14; len = strlen (host) + strlen (path) + 14;
*url = (char *) safemalloc (len); *url = (char *) saferealloc (*url, len);
if (*url == NULL) if (*url == NULL)
return -1; return -1;

View File

@ -27,12 +27,28 @@
#include "upstream.h" #include "upstream.h"
#include "heap.h" #include "heap.h"
#include "log.h" #include "log.h"
#include "base64.h"
#include "basicauth.h"
#ifdef UPSTREAM_SUPPORT #ifdef UPSTREAM_SUPPORT
const char *
proxy_type_name(proxy_type type)
{
switch(type) {
case PT_NONE: return "none";
case PT_HTTP: return "http";
case PT_SOCKS4: return "socks4";
case PT_SOCKS5: return "socks5";
default: return "unknown";
}
}
/** /**
* 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,
proxy_type type)
{ {
char *ptr; char *ptr;
struct upstream *up; struct upstream *up;
@ -44,8 +60,25 @@ static struct upstream *upstream_build (const char *host, int port, const char *
return NULL; return NULL;
} }
up->host = up->domain = NULL; up->type = type;
up->host = up->domain = up->ua.user = up->pass = NULL;
up->ip = up->mask = 0; up->ip = up->mask = 0;
if (user) {
if (type == PT_HTTP) {
char b[BASE64ENC_BYTES((256+2)-1) + 1];
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");
return NULL;
}
up->ua.authstr = safestrdup (b);
} else {
up->ua.user = safestrdup (user);
up->pass = safestrdup (pass);
}
}
if (domain == NULL) { if (domain == NULL) {
if (!host || host[0] == '\0' || port < 1) { if (!host || host[0] == '\0' || port < 1) {
@ -57,9 +90,9 @@ static struct upstream *upstream_build (const char *host, int port, const char *
up->host = safestrdup (host); up->host = safestrdup (host);
up->port = port; up->port = port;
log_message (LOG_INFO, "Added upstream %s:%d for [default]", log_message (LOG_INFO, "Added upstream %s %s:%d for [default]",
host, port); proxy_type_name(type), host, port);
} else if (host == NULL) { } else if (host == NULL || type == PT_NONE) {
if (!domain || domain[0] == '\0') { if (!domain || domain[0] == '\0') {
log_message (LOG_WARNING, log_message (LOG_WARNING,
"Nonsense no-upstream rule: empty domain"); "Nonsense no-upstream rule: empty domain");
@ -91,7 +124,7 @@ static struct upstream *upstream_build (const char *host, int port, const char *
log_message (LOG_INFO, "Added no-upstream for %s", domain); log_message (LOG_INFO, "Added no-upstream for %s", domain);
} else { } else {
if (!host || host[0] == '\0' || port < 1 || !domain if (!host || host[0] == '\0' || port < 1 || !domain
|| domain == '\0') { || domain[0] == '\0') {
log_message (LOG_WARNING, log_message (LOG_WARNING,
"Nonsense upstream rule: invalid parameters"); "Nonsense upstream rule: invalid parameters");
goto fail; goto fail;
@ -101,13 +134,15 @@ static struct upstream *upstream_build (const char *host, int port, const char *
up->port = port; up->port = port;
up->domain = safestrdup (domain); up->domain = safestrdup (domain);
log_message (LOG_INFO, "Added upstream %s:%d for %s", log_message (LOG_INFO, "Added upstream %s %s:%d for %s",
host, port, domain); proxy_type_name(type), host, port, domain);
} }
return up; return up;
fail: fail:
safefree (up->ua.user);
safefree (up->pass);
safefree (up->host); safefree (up->host);
safefree (up->domain); safefree (up->domain);
safefree (up); safefree (up);
@ -119,11 +154,12 @@ 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, void upstream_add (const char *host, int port, const char *domain,
struct upstream **upstream_list) const char *user, const char *pass,
proxy_type type, struct upstream **upstream_list)
{ {
struct upstream *up; struct upstream *up;
up = upstream_build (host, port, domain); up = upstream_build (host, port, domain, user, pass, type);
if (up == NULL) { if (up == NULL) {
return; return;
} }
@ -202,8 +238,8 @@ struct upstream *upstream_get (char *host, struct upstream *up)
up = NULL; up = NULL;
if (up) if (up)
log_message (LOG_INFO, "Found upstream proxy %s:%d for %s", log_message (LOG_INFO, "Found upstream proxy %s %s:%d for %s",
up->host, up->port, host); proxy_type_name(up->type), up->host, up->port, host);
else else
log_message (LOG_INFO, "No upstream proxy for %s", host); log_message (LOG_INFO, "No upstream proxy for %s", host);

View File

@ -31,17 +31,32 @@
* 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.
*/ */
typedef enum proxy_type {
PT_NONE = 0,
PT_HTTP,
PT_SOCKS4,
PT_SOCKS5
} proxy_type;
struct upstream { struct upstream {
struct upstream *next; struct upstream *next;
char *domain; /* optional */ char *domain; /* optional */
char *host; char *host;
union {
char *user;
char *authstr;
} ua;
char *pass;
int port; int port;
in_addr_t ip, mask; in_addr_t ip, mask;
proxy_type type;
}; };
#ifdef UPSTREAM_SUPPORT #ifdef UPSTREAM_SUPPORT
const char *proxy_type_name(proxy_type type);
extern void upstream_add (const char *host, int port, const char *domain, extern void upstream_add (const char *host, int port, const char *domain,
struct upstream **upstream_list); const char *user, const char *pass,
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);
#endif /* UPSTREAM_SUPPORT */ #endif /* UPSTREAM_SUPPORT */