Compare commits

..

56 Commits
master ... 1.6

Author SHA1 Message Date
Mukund Sivaraman
e16128d7e8 Bump version 2009-09-28 19:18:03 +05:30
Mukund Sivaraman
d304dda2f5 Further update Tinyproxy website URLs 2009-09-28 19:06:16 +05:30
Mukund Sivaraman
0655252925 Add NEWS for version 1.6.5 2009-09-28 19:04:55 +05:30
Mukund Sivaraman
a2ee837223 [BB#10] Do not filter out transfer-encoding header 2009-09-27 16:30:54 +05:30
Mukund Sivaraman
ef09a6bcc1 [BB#18] Fix pointer aliasing issues
The changes were suggested by ians on the Banu forums.
2009-09-21 09:36:31 +05:30
Robert James Kaes
33f7405bf5 * [1118363] Proxy reverse order of headers
Changed the internal implementation of the hashmap to maintain the
  insert order if the same key is repeated.  The insertion is still
  constant since we keep track of the head and tail of the bucket
  chain.

Signed-off-by: Michael Adam <obnox@samba.org>
2009-08-04 01:25:51 +02:00
Mukund Sivaraman
bb489a5570 [BB#53] Add a GPLv2 COPYING file
Tinyproxy is distributed under the GNU GPLv2 or above license.
If autotools are used to build Tinyproxy without this file, they
copy the system installed COPYING file which is nowadays the
GNU GPLv3 license.
2009-08-04 04:23:56 +05:30
Mukund Sivaraman
82e3af8fd3 Fix memset bug where wrong buffer size was being passed (trac #29)
This bug was reported by devy at free dot fr. It had already been
fixed in the master branch.
2008-12-29 13:31:08 +00:00
Mukund Sivaraman
d5148b0b73 Update Tinyproxy website URLs 2008-10-16 18:28:38 +01:00
Mukund Sivaraman
a46a02dbf7 Tweak configure.ac a bit 2008-08-24 12:26:11 +05:30
Mukund Sivaraman
7518fbb956 Update the bugmail address 2008-08-24 12:15:26 +05:30
Mukund Sivaraman
08b4e06247 Fix leak of args 2008-08-24 12:09:17 +05:30
Mukund Sivaraman
fc815b12c1 Move buffer to the heap due to its size 2008-08-24 12:07:24 +05:30
Mukund Sivaraman
b6bd791e24 Set umask before mkstemp() for some versions of glibc 2008-08-24 12:02:54 +05:30
Mukund Sivaraman
ee70057f76 Fix leak of entry_buffer 2008-08-24 11:59:24 +05:30
Mukund Sivaraman
a7f379fafc pos can never be less than 0 as it's of type size_t
Also fix the type which is passed in from various places.
2008-08-24 11:55:22 +05:30
Mukund Sivaraman
1e44781c4d Remove unused autoconf macro calls 2008-07-30 19:35:48 +05:30
Mukund Sivaraman
bb5bbb6431 Fix the bug-report field 2008-07-30 18:53:17 +05:30
Jeremy Hinegardner
fbb43fb72b fix building of Makefiles in packaging subtree
When ./configure is run, the Makfiles in the packaging subtree's
Makefiles are not created.  As a result, the 'make dist' command will
fail when it attempts to recurse through ./packaging.

Signed-off-by: Jeremy Hinegardner <jeremy@hinegardner.org>
2008-06-24 12:33:17 +05:30
Mukund Sivaraman
20ac984707 Add new Fedora packaging files
These spec files were made by Jeremy Hinegardner <jeremy@hinegardner.org>
and backported from master to the 1.6 branch by me.

X-Banu-Bugzilla-Ids: 11
2008-06-19 22:09:22 +05:30
Mukund Sivaraman
4a993787ca Remove obsolete packaging files 2008-06-19 22:09:22 +05:30
Mukund Sivaraman
100cc20291 Remove releases.txt from EXTRA_DIST 2008-06-19 22:09:22 +05:30
Mukund Sivaraman
e9c5ecedba Bump version to 1.6.4 2008-06-19 22:09:21 +05:30
Mukund Sivaraman
f4af613d48 Don't use config directory for aclocal 2008-06-19 22:09:21 +05:30
Mukund Sivaraman
742248b600 Remove Id tag from configure.ac 2008-06-19 22:09:21 +05:30
Mukund Sivaraman
7f189fb730 Ignore ylwrap 2008-06-19 22:09:21 +05:30
Mukund Sivaraman
02054cef92 Add src/.gitignore 2008-06-19 22:09:21 +05:30
Mukund Sivaraman
8784e32e25 Add top-level .gitignore 2008-06-19 22:09:20 +05:30
Mukund Sivaraman
61f8ab527c Fix format strings for size_t 2008-06-19 22:09:20 +05:30
Mukund Sivaraman
92f5bdce14 Use socklen_t for sizeof sockaddr_in 2008-05-31 19:11:25 +05:30
Mukund Sivaraman
0a16445b69 Don't override YFLAGS and LDFLAGS 2008-05-31 19:08:56 +05:30
Mukund Sivaraman
1df038294b Removed the clean target from the src directory 2008-05-11 16:11:59 +05:30
Mukund Sivaraman
893aaabe9c Added autogen.sh 2008-05-11 16:09:17 +05:30
Mukund Sivaraman
c82f07a021 Added required file NEWS 2008-05-11 16:09:05 +05:30
Mukund Sivaraman
9f37380de5 Added required file ltmain.sh 2008-05-11 16:08:59 +05:30
Robert James Kaes
1768fc0755 # Updated changelog to reflect that 1.6.3 is released today. 2004-08-10 20:03:16 +00:00
Robert James Kaes
bebc78a7e6 # Updated changelog 2004-08-10 15:34:48 +00:00
Robert James Kaes
4a8c4d55f0 Close the standard file descriptors (stdin, stdout, and stderr) when
compiling in production mode (no debugging information.)
2004-08-10 03:38:13 +00:00
Robert James Kaes
c6711d7d38 # Real update. The last changelog update also included updates from HEAD 2004-08-09 20:43:02 +00:00
Robert James Kaes
c120c62fd9 # Updated changelog 2004-08-09 18:52:23 +00:00
Robert James Kaes
05ed84f04c # Updated version number 2004-08-09 18:48:48 +00:00
Robert James Kaes
385fae593d [Fixes Bug 996518]
Merged in a patch from Hans-Dieter that fixes a problem with upstream
proxy support.
2004-08-06 16:56:55 +00:00
Robert James Kaes
cde61e2fac child_configure(): Change the "val" type to a signed integer. 2004-06-14 20:49:57 +00:00
Robert James Kaes
cc3a893f5a Changed the fields in the child_config_s structure to use regular
signed integers since the servers_waiting variable is signed and
therefore, all the tests must use signed arithmetic.
2004-06-14 20:08:12 +00:00
Robert James Kaes
cd9c768c59 (upstream_add): Fixed a spelling mistake with "Nonsence" 2003-11-19 19:20:18 +00:00
Robert James Kaes
acb5026545 # Updated ChangeLog 2003-10-17 15:43:33 +00:00
Robert James Kaes
53ad8ef067 # Bumped up the version number 2003-10-17 15:39:23 +00:00
Robert James Kaes
d475d44cc0 Removed a redundant "mkdir" command, since the $(mkinstalldirs)
command handles it correctly.
2003-10-17 15:38:28 +00:00
Robert James Kaes
b1d126c4bb (filter_init): Fixed up the comment handling code. Closes bug 822226
[https://sourceforge.net/tracker/index.php?func=detail&aid=822226&group_id=2632&atid=102632]
2003-10-16 21:19:09 +00:00
Robert James Kaes
b8d7ee66a5 Added a missing $(DESTDIR) to the tinyproxy-html-files rule. Thanks
to Ed Boraas for pointing this out.
2003-08-14 15:13:24 +00:00
Robert James Kaes
4f48cb16c7 # Bumped up the version number 2003-08-06 20:52:08 +00:00
Robert James Kaes
074af84f63 # Updated changelog 2003-08-06 20:51:45 +00:00
Robert James Kaes
e04dd2ee69 # Misspelled the __cplusplus define. 2003-08-06 20:46:04 +00:00
Robert James Kaes
c315bce11b (debugging_realloc): Remove the assert on the ptr being NULL since a
NULL pointer is allowed by the realloc() spec.
2003-08-06 20:44:09 +00:00
Robert James Kaes
6a11a9c909 (child_main): Fixed an off-by-one error with the maxrequestsperchild
variable.  [Fix proposed by Yannick Koehler]
2003-08-06 20:23:06 +00:00
cvs2svn
4beea1ac67 This commit was manufactured by cvs2svn to create branch
'release_1_6_patches'.
2003-07-14 17:45:12 +00:00
149 changed files with 16108 additions and 12218 deletions

View File

@ -1,20 +0,0 @@
---
name: New Issue, Bug report, Question
about: New Issue, Bug report, Question
title: ''
labels: ''
assignees: ''
---
# IMPORTANT NOTICE
Before filing an issue here PLEASE keep in mind that **tinyproxy 1.10.0 and older are no longer supported**.
Do not report issues with 1.10.0 or older, first try latest release 1.11.0, or even better, git master, and see whether the issue is already fixed.
## Tinyproxy version
State the tinyproxy version you're using; whether git master or 1.11.0 stable.
## Issue
Fill in your Issue text here.
A good issue report is detailed and includes full error messages from tinyproxy's output, not "X doesn't work".

View File

@ -1,36 +0,0 @@
name: CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: ./autogen.sh
- run: ./configure
- run: make
- run: make test
test-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- run: brew install automake
- run: ./autogen.sh
- run: ./configure
- run: make
valgrind-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: sudo apt update
- run: sudo apt install --assume-yes valgrind
- run: ./autogen.sh
- run: ./configure --enable-debug --enable-transparent --enable-reverse
- run: make
- run: make test
- run: make valgrind-test

View File

@ -1,40 +0,0 @@
name: Generate Source Tarball
# Trigger whenever a release is created
on:
release:
types:
- created
jobs:
build:
name: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: archive
id: archive
run: |
sudo apt install -y gperf
rm -rf .git
autoreconf -i
VERSION=$(cat VERSION)
PKGNAME="tinyproxy-$VERSION"
./configure
make dist
echo "tarball_xz=${PKGNAME}.tar.xz" >> "$GITHUB_OUTPUT"
echo "tarball_gz=${PKGNAME}.tar.gz" >> "$GITHUB_OUTPUT"
echo "tarball_bz2=${PKGNAME}.tar.bz2" >> "$GITHUB_OUTPUT"
- name: upload tarballs
uses: softprops/action-gh-release@v2
with:
files: |
${{ steps.archive.outputs.tarball_xz }}
${{ steps.archive.outputs.tarball_gz }}
${{ steps.archive.outputs.tarball_bz2 }}

5
.gitignore vendored
View File

@ -14,10 +14,9 @@ depcomp
install-sh
libtool
missing
mkinstalldirs
stamp-h1
ylwrap
autom4te.cache
cscope.files
cscope.out
compile
*~
tags

View File

@ -1,18 +0,0 @@
language: C
dist: trusty
sudo: true
before_install:
- sudo apt-get update -qq
- sudo apt-get install --assume-yes valgrind
script:
- ./autogen.sh
- ./configure
- make
- make test
- make clean
- ./configure --enable-debug --enable-transparent --enable-reverse
- make
- make test
- make valgrind-test

51
AUTHORS
View File

@ -1,39 +1,12 @@
Andrew Stribblehill
bertliao
Bob Showalter
Brian Cain
cvs2svn
Daniel Egger
Daniel M. Drucker
David Shanks
Dmitry Semyonov
dmz-uk
Drew G. Wallace
Frank Morgner
gary-wzl77
Gaudenz Steinlin
goba62000374
Gonzalo Tornaria
Greg
Jeremy Hinegardner
John Spencer
John van der Kamp
John Weldon
Jordi
Jordi Mallach
Julien Hartmann
kikuchan
Mathew Mrosko
Matthew Dempsky
Michael Adam
Mike Mead
Mukund Sivaraman
Pablo Panero
Peter H. Froehlich
Robert James Kaes
rofl0r
Stephan Leemburg
Steven Conaway
Steven Young
Valen Blanco
Vladimir Belov
tinyproxy is a collaborative work between Steven Young
<sdyoung@well.com> and Robert James Kaes <rjkaes@flarenet.com>.
From versions 0-1.1, Steven Young was the primary maintainer.
From 1.2 to 1.3.0, Robert James Kaes was the primary maintainer.
As of 1.3.1, Steven Young was once again be the primary maintainer.
But, Robert James Kaes was again the maintainer starting with 1.4.0.
Place your bets as to when the maintainer will change again. :) Kidding!
Please see the ChangeLog for futher details as to who did what. :)

2164
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,38 @@
SUBDIRS = \
src \
data \
etc \
docs \
m4macros \
tests \
scripts
EXTRA_DIST = $(CONFIG_FILES) TODO autogen.sh
SUBDIRS = src doc packaging
# tools want this on a single line
ACLOCAL_AMFLAGS = -I m4macros
install-data-local: tinyproxy-configure-file tinyproxy-html-files
all-local:
# Install the configuration file if it doesn't already exist
tinyproxy-configure-file:
$(mkinstalldirs) $(DESTDIR)@TINYPROXY_CONFIG_DIR@
$(INSTALL) -m 600 $(srcdir)/doc/tinyproxy.conf \
$(DESTDIR)@TINYPROXY_CONFIG_DIR@/@TINYPROXY_CONFIG_FILE@-dist
test -f $(DESTDIR)@TINYPROXY_CONFIG_DIR@/@TINYPROXY_CONFIG_FILE@ \
|| $(INSTALL) -m 600 $(srcdir)/doc/tinyproxy.conf \
$(DESTDIR)@TINYPROXY_CONFIG_DIR@/@TINYPROXY_CONFIG_FILE@
@echo ""
@echo "A configuration file has been copied to:"
@echo ""
@echo "@TINYPROXY_CONFIG_DIR@/@TINYPROXY_CONFIG_FILE@-dist"
@echo ""
@echo "You will need to rename this file to:"
@echo ""
@echo "@TINYPROXY_CONFIG_DIR@/@TINYPROXY_CONFIG_FILE@"
@echo ""
@echo "and modify the values to suit your local system."
@echo ""
@echo "All the configuration directives are commented in the file, so"
@echo "you should not have any problems configuring your system."
@echo ""
dist_doc_DATA = \
AUTHORS \
NEWS \
README \
README.md
# Install the HTML files
tinyproxy-html-files:
$(mkinstalldirs) $(DESTDIR)$(datadir)/tinyproxy
EXTRA_DIST = \
autogen.sh \
tinyproxy-indent.sh \
TODO \
VERSION
test: all
./tests/scripts/run_tests.sh
test-wait:
TINYPROXY_TESTS_WAIT=yes $(MAKE) test
valgrind-test: all
./tests/scripts/run_tests_valgrind.sh
valgrind-test-wait:
TINYPROXY_TESTS_WAIT=yes $(MAKE) valgrind-test
for file in debug default stats; do \
$(INSTALL) -m 644 $(srcdir)/doc/$$file.html $(DESTDIR)$(datadir)/tinyproxy/$$file.html.dist ; \
test -f $(DESTDIR)$(datadir)/tinyproxy/$$file.html || \
$(INSTALL) -m 644 $(srcdir)/doc/$$file.html $(DESTDIR)$(datadir)/tinyproxy/$$file.html ; \
done
$(INSTALL) -m 644 $(srcdir)/doc/HTML_VARIABLES $(DESTDIR)$(datadir)/tinyproxy/HTML_VARIABLES

23
NEWS
View File

@ -1 +1,22 @@
See git log for recent changes in Tinyproxy.
Tinyproxy NEWS
==============
Version 1.6.5
-------------
* Fixed memset bug where wrong buffer size was being passed
* Updated Tinyproxy website URLs
* Fixed various other bugs
Bugs fixed since version 1.6.4
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* BB#10: Do not filter out transfer-encoding header
* BB#14: Do not change order of HTTP headers
* BB#18: Fix pointer aliasing issues
* BB#53: Add a GPLv2 COPYING file
Contributors
~~~~~~~~~~~~
Michael Adam, Mukund Sivaraman, Robert James Kaes.

110
README
View File

@ -1 +1,109 @@
see README.md
DESCRIPTION
-----------
tinyproxy is a small, efficient HTTP/SSL proxy daemon released under
the GNU General Public License (GPL). tinyproxy is very useful in a
small network setting, where a larger proxy like Squid would either
be too resource intensive, or a security risk. One of the key
features of tinyproxy is the buffering connection concept. In
effect, tinyproxy will buffer a high speed response from a server,
and then relay it to a client at the highest speed the client will
accept. This feature greatly reduces the problems with sluggishness
on the Internet. If you are sharing an Internet connection with a
small network, and you only want to allow HTTP requests to be
allowed, then tinyproxy is a great tool for the network
administrator.
For more info, please visit: https://www.banu.com/tinyproxy/
INSTALLATION
------------
To install this package under a Unix derivative, read the INSTALL
file. tinyproxy uses a standard GNU configure script (basically you
should be able to do:
./configure ; make ; make install
in the top level directory to compile and install tinyproxy). There
are additional command line arguments you can supply to configure.
They include:
--enable-debug If you would like to turn on full
debugging support
--enable-socks This turns on SOCKS support for using
tinyproxy across a fire wall.
--enable-xtinyproxy Compile in support for the XTinyproxy
header, which is sent to any web
server in your domain.
--enable-filter Allows tinyproxy to filter out certain
domains and URLs.
--enable-upstream Enable support for proxying connections
through another proxy server.
--enable-transparent-proxy
Allow tinyproxy to be used as a
transparent proxy daemon
--enable-static Compile a static version of tinyproxy
Options for file locations etc.
--with-stathost=HOST Set the default name of the stats host
--with-config=FILE Set the default location of the
configuration file
Once you have completed your installation, if you would like to
report your success please execute the report.sh script in the doc
directory. This will send an email to the authors reporting your
version, and a few bits of information concerning the memory usage of
tinyproxy. Alternatively, you could just send an email stating the
version, whichever you prefer.
SUPPORT
-------
If you are having problems with tinyproxy, please submit a bug at:
https://www.banu.com/bugzilla/enter_bug.cgi?product=Tinyproxy
You may also wish to subscribe to the tinyproxy mailing lists. To do
so please visit:
https://www.banu.com/mailman/listinfo/tinyproxy-announce-list
https://www.banu.com/mailman/listinfo/tinyproxy-users-list
https://www.banu.com/mailman/listinfo/tinyproxy-developers-list
for more information on how to subscribe and post messages to the
lists.
Please recompile tinyproxy with full debug support (--enable-debug)
and include a copy of the log file, and any assert errors reported by
tinyproxy. Note that tinyproxy will output memory statistics to
standard error if compiled with debugging support so you might want
to redirect the output to a file for later examination. Also, if you
feel up to it, try running tinyproxy under your debugger and report
the error your received and a context listing of the location. Under
gdb you would run tinyproxy like so:
gdb tinyproxy
(gdb) run -c location_of_tinyproxy_conf -d 2>/dev/null
Now access the port tinyproxy is on until you receive a break in the
gdb. You can now type:
(gbd) l
to produce a context listing of the location of the error. Send a
copy to the authors.
HOW TO CONTRIBUTE TO tinyproxy
------------------------------
If you would like to contribute a feature, or a bug fix to the
tinyproxy source, please send a diff (preferable a unified
diff. i.e. "diff -u") against the latest release of tinyproxy. Also,
if you could include a brief description of what your patch does.

View File

@ -1,92 +0,0 @@
# Tinyproxy
Tinyproxy is a small, efficient HTTP/SSL proxy daemon released under the
GNU General Public License. Tinyproxy is very useful in a small network
setting, where a larger proxy would either be too resource intensive, or
a security risk. One of the key features of Tinyproxy is the buffering
connection concept. In effect, Tinyproxy will buffer a high speed
response from a server, and then relay it to a client at the highest
speed the client will accept. This feature greatly reduces the problems
with sluggishness on the Internet. If you are sharing an Internet
connection with a small network, and you only want to allow HTTP
requests to be allowed, then Tinyproxy is a great tool for the network
administrator.
For more info, please visit [the Tinyproxy web site](https://tinyproxy.github.io/).
## Installation
Tinyproxy uses a standard GNU `configure` script based on the automake
system. If compiling from a git checkout, you need to first run
```
./autogen.sh
```
from the top level directory to generate the `configure` script.
The release tarball contains the pre-created `configure` script,
so when building from a release, you can skip this step.
Then basically all you need to do is
```
./configure
make
make install
```
in the top level directory to compile and install Tinyproxy. There are
additional command line arguments you can supply to `configure`. They
include:
- `--enable-debug`:
If you would like to turn on full debugging support.
- `--enable-xtinyproxy`:
Compile in support for the XTinyproxy header, which is sent to any
web server in your domain.
- `--enable-filter`:
Allows Tinyproxy to filter out certain domains and URLs.
- `--enable-upstream`:
Enable support for proxying connections through another proxy server.
- `--enable-transparent`:
Allow Tinyproxy to be used as a transparent proxy daemon.
Unlike other work modes, transparent proxying doesn't require explicit
configuration and works automatically when traffic is redirected to
the proxy using the appropriate firewall rules.
- `--enable-reverse`:
Enable reverse proxying.
- `--with-stathost=HOST`:
Set the default name of the stats host.
For more information about the build system, read the INSTALL file
that is generated by `autogen.sh` and comes with the release tar ball.
## Support
If you are having problems with Tinyproxy, please raise an
[issue on github](https://github.com/tinyproxy/tinyproxy/issues).
## Contributing
If you would like to contribute a feature, or a bug fix to the Tinyproxy
source, please clone the
[git repository from github](https://github.com/tinyproxy/tinyproxy.git)
and create a [pull request](https://github.com/tinyproxy/tinyproxy/pulls).
## Community
You can meet developers and users to discuss development,
patches and deployment issues in the `#tinyproxy` IRC channel on
libera (`irc.libera.chat`).

View File

@ -1,28 +0,0 @@
# Security Policy
## Supported Versions
| Version | Supported |
| --------- | ------------------ |
| 1.11.x | :white_check_mark: |
| <= 1.10.x | :x: |
## Reporting a Vulnerability
Open a public issue on github. The issue will most likely be fixed
within a day, unless all maintainers happen to just be taking a
vacation at the same time, which is unlikely.
Even then, having the bug publicly known will allow competent people
to come up with custom patches for distros, most likely quicker
than black hats can craft a remote execution exploit.
If you really really do not want to make the issue public, come
to the tinyproxy IRC channel and ask for a maintainer, which you
can then contact via private messages.
Do not, however, like ["TALOS Intelligence"](https://talosintelligence.com/vulnerability_reports/TALOS-2023-1889)
pull a random email address out of git log, then send an email
nobody reads or responds to, and wait for 6 months for publication.
this only gives black hats plenty time to sell, use and circulate
zero days and get the best possible ROI.

13
TODO
View File

@ -38,15 +38,4 @@ against the current tree and I'll integrate it if possible.
* Include user authentication for accessing tinyproxy itself.
Administrators should be allowed to selectively allow certain users
access to tinyproxy via a user name/password pair. Check the
HTTP/1.1 RFC for more information.
==> https://www.banu.com/bugzilla/show_bug.cgi?id=13
* Remove common.h and fix order of headers
* Remove memory debugging functions (Valgrind is good enough)
* Make all functions return from one place (the end of the function)
* Move TODO items to Banu Bugzilla
HTTP/1.1 RFC for more information. [Suggested: Tyrone Tranmer]

View File

@ -1 +0,0 @@
1.11.2

103
acinclude.m4 Normal file
View File

@ -0,0 +1,103 @@
dnl Taken from Unix Network Programming, W. Richard Stevens
dnl ##################################################################
dnl We cannot use the AC_CHECK_TYPE macros becasue AC_CHECK_TYPE
dnl #includes only <sys/types.h>, <stdlib.h>, and <stddef.h>.
dnl Unfortunately, many implementations today hide typedefs in wierd
dnl locations: Solaris 2.5.1 has uint8_t and uint32_t in <pthread.h>.
dnl SunOS 4.1.x has int8_t in <sys/bittypes.h>.
dnl So we define our own macro AC_UNP_CHECK_TYPE that does the same
dnl #includes as "unp.h", and then looks for the typedef.
dnl
dnl This macro should be invoked after all the header checks have been
dnl performed, since we #include "confdefs.h" below, and then use the
dnl HAVE_foo_H values that is can #define.
dnl
AC_DEFUN([AC_UNP_CHECK_TYPE],
[AC_MSG_CHECKING(if $1 defined)
AC_CACHE_VAL(ac_cv_type_$1,
[AC_TRY_COMPILE(
[
#include "confdefs.h" /* the header built by configure so far */
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_ERRNO_H
# include <errno.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_UIO_H
# include <sys/uio.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#ifdef HAVE_SYS_UN_H
# include <sys/un.h>
#endif
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_FILIO_H
# include <sys/filio.h>
#endif
#ifdef HAVE_SYS_SOCKIO_H
# include <sys/sockio.h>
#endif
#ifdef HAVE_PTHREAD_H
# include <pthread.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
],
[ $1 foo ],
[ac_cv_type_$1=yes],
[ac_cv_type_$1=no])])
AC_MSG_RESULT([$ac_cv_type_$1])
if test $ac_cv_type_$1 = no ; then
AH_TEMPLATE([$1], [Defined with the proper type.])
AC_DEFINE($1, $2)
fi
])

View File

@ -1,30 +1,13 @@
#!/bin/sh
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
# -*- sh -*-
#
# Make the Autotools scripts after checking out the source code from CVS.
# This script was taken from the Autotool Book. I wonder if autoreconf
# can now be used...
#
set -x
cd $srcdir
aclocal -I m4macros \
aclocal \
&& autoheader \
&& automake --gnu --add-missing \
&& autoconf
cd $ORIGDIR
set -
echo $srcdir/configure "$@"
$srcdir/configure "$@"
RC=$?
if test $RC -ne 0; then
echo
echo "Configure failed or did not finish!"
exit $RC
fi
echo
echo "Now type 'make' to compile Tinyproxy."

View File

@ -1,57 +1,88 @@
# Process this file with autoconf to produce a configure script.
# Portions of this file were adapted from GIMP.
AC_PREREQ(2.54)
m4_define([tinyproxy_version], esyscmd(sh scripts/version.sh | tr -d '\n'))
AC_INIT([Tinyproxy], [tinyproxy_version],
[https://tinyproxy.github.io/],
[tinyproxy])
tpv=tinyproxy_version
if test "x$tpv" = "x" ; then
AC_MSG_ERROR([got empty result from version script!])
fi
AC_INIT([Tinyproxy], [1.6.5], [https://www.banu.com/bugzilla/enter_bug.cgi?product=Tinyproxy], [tinyproxy])
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([dist-bzip2 dist-xz])
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_MACRO_DIR([m4macros])
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
dnl Temporarily defined here until we get tinyproxy-version.h
AC_DEFINE(TINYPROXY_VERSION, "tinyproxy_version", [Tinyproxy version number])
AH_TEMPLATE([TARGET_SYSTEM],
[A string containing the target system for which tinyproxy was built.])
AC_DEFINE_UNQUOTED(TARGET_SYSTEM, ["$target"])
dnl Check if we're compiling on a weird platform :)
AC_USE_SYSTEM_EXTENSIONS
AC_AIX
AC_GNU_SOURCE
AC_MINIX
dnl
dnl Command line options
dnl
dnl Set the domain name for find the statistics of tinyproxy
AH_TEMPLATE([TINYPROXY_STATHOST],
dnl Set the URL name for find the statistics of tinyproxy
AH_TEMPLATE([DEFAULT_STATHOST],
[This controls remote proxy stats display.])
AC_ARG_WITH(stathost,
[AC_HELP_STRING([--with-stathost=HOST], [Default status host])],
[AC_DEFINE_UNQUOTED(TINYPROXY_STATHOST, "$withval")
TINYPROXY_STATHOST="$withval"],
[AC_DEFINE_UNQUOTED(TINYPROXY_STATHOST, "tinyproxy.stats")
TINYPROXY_STATHOST="tinyproxy.stats"])
[AC_DEFINE_UNQUOTED(DEFAULT_STATHOST, "$withval")],
[AC_DEFINE_UNQUOTED(DEFAULT_STATHOST, "tinyproxy.stats")])
AC_SUBST(TINYPROXY_STATHOST)
dnl Set the default configuration file location
test "$prefix" = "NONE" && prefix=/usr/local
AH_TEMPLATE([DEFAULT_CONF_FILE],
[This is the default file name for the configuration file.])
AC_ARG_WITH(config,
[AC_HELP_STRING([--with-config=FILE],
[Set the default location of the config file])],
[tp_config_file="$withval"],
[tp_config_file="tinyproxy.conf"])
# If the first character is a slash, it's an absolute path
if [[ `echo $tp_config_file | cut -c1` = "/" ]]; then
TINYPROXY_CONFIG_DIR=`echo "$tp_config_file" | sed 's/^\(.*\)\/[[^\/]]*$/\1/'`
TINYPROXY_CONFIG_FILE=`echo "$tp_config_file" | sed 's/^.*\/\([[^\/]]*\)$/\1/'`
else
# If sysconfdir is /usr/etc, change it to /etc (since /usr/etc doesn't exist)
if [[ "/usr/etc" = `eval echo $sysconfdir` -a "/usr" = "$prefix" ]]; then
TINYPROXY_CONFIG_DIR="/etc/tinyproxy"
else
TINYPROXY_CONFIG_DIR=`eval echo $sysconfdir/tinyproxy`
fi
TINYPROXY_CONFIG_FILE="$tp_config_file"
fi
AC_DEFINE_UNQUOTED(DEFAULT_CONF_FILE, "$TINYPROXY_CONFIG_DIR/$TINYPROXY_CONFIG_FILE")
AC_MSG_NOTICE([Default config location and file is: $TINYPROXY_CONFIG_DIR/$TINYPROXY_CONFIG_FILE])
dnl Add compiler-specific optimization flags
TP_ARG_ENABLE(debug,
[Enable debugging support code and methods (default is NO)],
no)
AC_ARG_ENABLE(debug,
[AC_HELP_STRING([--enable-debug],
[Disable aggressive optimizations (default is NO)])],
debug_enabled=$enableval, debug_enabled=no)
dnl Add in profiling information
AC_ARG_ENABLE(profiling,
[AC_HELP_STRING([--enable-profiling],
[Enable profiling information (default is NO)])],
profiling_enabled=$enableval, profiling_enabled=no)
dnl Include SOCKS support
AC_ARG_ENABLE(socks,
[AC_HELP_STRING([--enable-socks],
[Enable SOCKS support (default is NO)])],
socks_enabled=$enableval, socks_enabled=no)
dnl Check to see if the XTinyproxy header is to be included
AH_TEMPLATE([XTINYPROXY_ENABLE],
[Define if you want to have the peer's IP address included in a XTinyproxy header sent to the server.])
TP_ARG_ENABLE(xtinyproxy,
[Include the X-Tinyproxy header (default is YES)],
yes)
AC_ARG_ENABLE(xtinyproxy,
[AC_HELP_STRING([--enable-xtinyproxy],
[Include X-Tinyproxy header (default is YES)])],
xtinyproxy_enabled=$enableval, xtinyproxy_enabled=yes)
if test x"$xtinyproxy_enabled" = x"yes"; then
AC_DEFINE(XTINYPROXY_ENABLE)
@ -60,9 +91,10 @@ fi
dnl Include filtering for domain/URLs
AH_TEMPLATE([FILTER_ENABLE],
[Defined if you would like filtering code included.])
TP_ARG_ENABLE(filter,
[Enable filtering of domains/URLS (default is YES)],
yes)
AC_ARG_ENABLE(filter,
[AC_HELP_STRING([--enable-filter],
[Enable filtering of domains/URLs (default is YES)])],
filter_enabled=$enableval, filter_enabled=yes)
if test x"$filter_enabled" = x"yes"; then
ADDITIONAL_OBJECTS="$ADDITIONAL_OBJECTS filter.o"
@ -72,46 +104,55 @@ fi
dnl Include support for upstream proxies?
AH_TEMPLATE([UPSTREAM_SUPPORT],
[Include support for connecting to an upstream proxy.])
TP_ARG_ENABLE(upstream,
[Enable upstream proxying (default is YES)],
yes)
AC_ARG_ENABLE(upstream,
[AC_HELP_STRING([--enable-upstream],
[Enable support for upstream proxies (default is YES)])],
upstream_enabled=$enableval, upstream_enabled=yes)
if test x"$upstream_enabled" = x"yes"; then
AC_DEFINE(UPSTREAM_SUPPORT)
fi
dnl Include support for reverse proxy?
AH_TEMPLATE([REVERSE_SUPPORT],
[Include support for reverse proxy.])
TP_ARG_ENABLE(reverse,
[Enable reverse proxying (default is YES)],
yes)
if test x"$reverse_enabled" = x"yes"; then
ADDITIONAL_OBJECTS="$ADDITIONAL_OBJECTS reverse-proxy.o"
AC_DEFINE(REVERSE_SUPPORT)
fi
dnl Include the transparent proxy support
AH_TEMPLATE([TRANSPARENT_PROXY],
[Include support for using tinyproxy as a transparent proxy.])
TP_ARG_ENABLE(transparent,
[Enable transparent proxying code (default is YES)],
yes)
AC_ARG_ENABLE(transparent-proxy,
[AC_HELP_STRING([--enable-transparent-proxy],
[Enable transparent proxy support (default is NO)])],
transparent_enabled=$enableval, transparent_enabled=no)
if test x"$transparent_enabled" = x"yes"; then
ADDITIONAL_OBJECTS="$ADDITIONAL_OBJECTS transparent-proxy.o"
AC_DEFINE(TRANSPARENT_PROXY)
fi
dnl Let user decide whether he wants support for manpages
dnl Which require either pod2man or a tarball release
AH_TEMPLATE([MANPAGE_SUPPORT],
[Build manpages with pod2man if they are missing from the distribution.])
TP_ARG_ENABLE(manpage_support,
[Enable support for building manpages (default is YES)],
yes)
AM_CONDITIONAL(HAVE_MANPAGE_INTEREST, test x"$manpage_support_enabled" = x"yes")
dnl Include support for a statically compiled tinyproxy
AC_ARG_ENABLE(static,
[AC_HELP_STRING([--enable-static],
[Statically link tinyproxy (default is NO)])],
[LDFLAGS="-static $LDFLAGS"])
# This is required to build test programs below
dnl
dnl Checks for programs
dnl
AC_PROG_MAKE_SET
AC_PROG_CC
AC_ISC_POSIX
AC_PROG_INSTALL
AM_PROG_LEX
AC_PROG_YACC
dnl If a CFLAGS variable was passed during configure, set the initial
dnl CFLAGS variable to it; otherwise, start with an empty CFLAGS
if test x"$ac_env_CFLAGS_set" = x"set" ; then
CFLAGS=$ac_env_CFLAGS_value
else
CFLAGS=""
fi
dnl Make sure YACC is actually bison
if test x"$YACC" != x"bison -y"; then
AC_MSG_WARN([You will need bison if you want to regenerate the parser.])
fi
dnl
dnl Checks for libraries
@ -133,121 +174,165 @@ if test x"$tinyproxy_no_nsl_checks" != x"yes"; then
fi
AC_CHECK_LIB(resolv, inet_aton)
AC_CHECK_LIB(socks, main, socks_library=yes, socks_library=no)
dnl
dnl Checks for headers
dnl
AC_HEADER_STDC
AC_HEADER_TIME
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([sys/ioctl.h alloca.h memory.h malloc.h sysexits.h \
values.h poll.h])
AC_CHECK_HEADERS([sys/ioctl.h sys/mman.h sys/resource.h \
sys/select.h sys/socket.h sys/time.h sys/uio.h \
sys/un.h sys/wait.h arpa/inet.h netinet/in.h alloca.h \
assert.h ctype.h errno.h fcntl.h grp.h io.h libintl.h \
netdb.h pwd.h regex.h signal.h stdarg.h stddef.h stdio.h \
sysexits.h syslog.h time.h wchar.h wctype.h])
dnl OpenBSD machines don't like having malloc included (even if it's present)
dnl as they expect you to use stdlib.h
case "$target" in
*-openbsd*) ;;
*) AC_CHECK_HEADER(malloc.h);;
esac
AC_CHECK_HEADER(socks.h, socks_header=yes, socks_header=no)
dnl
dnl Checks for types
dnl
AM_C_PROTOTYPES
AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
AC_TYPE_PID_T
AC_TYPE_SIGNAL
AC_UNP_CHECK_TYPE(uint8_t, unsigned char)
AC_UNP_CHECK_TYPE(int16_t, short)
AC_UNP_CHECK_TYPE(uint16_t, unsigned short)
AC_UNP_CHECK_TYPE(int32_t, int)
AC_UNP_CHECK_TYPE(uint32_t, unsigned int)
AC_UNP_CHECK_TYPE(ssize_t, int)
AC_UNP_CHECK_TYPE(socklen_t, unsigned int)
AC_UNP_CHECK_TYPE(in_addr_t, uint32_t)
dnl
dnl Checks for libary functions
AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
dnl
AC_FUNC_ALLOCA
AC_CHECK_FUNCS([strlcpy strlcat setgroups])
AC_CHECK_FUNCS([isascii memcpy setrlimit ftruncate regexec])
AC_CHECK_FUNCS([strlcpy strlcat])
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 -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"
dnl
dnl Compiler characteristics
dnl
if test -n "${MAINTAINER_MODE_FALSE}"; then
DESIRED_FLAGS="-Werror $DESIRED_FLAGS"
dnl If profiling is enabled, then enable the debugging code
if test x"$profiling_enabled" = x"yes" ; then
AC_MSG_NOTICE([profiling is enabled, therefore enabling debugging code.])
debug_enabled=yes
fi
all_desired_work=false
AS_COMPILER_FLAG([$DESIRED_FLAGS], [all_desired_work=true])
if $all_desired_work ; then
CFLAGS="$CFLAGS $DESIRED_FLAGS"
dnl Enable the debugging flags (by checking for the GCC compiler)
if test x"$debug_enabled" = x"yes" ; then
dnl Add the warnings if we have the GCC compiler
if test x"$GCC" = x"yes" ; then
if test x"$profiling_enabled" = x"yes" ; then
CFLAGS="-pg -fprofile-arcs $CFLAGS"
fi
CFLAGS="-Wshadow -Wcast-qual -Wcast-align -Wstrict-prototypes $CFLAGS"
CFLAGS="-Wmissing-prototypes -Wmissing-declarations $CFLAGS"
CFLAGS="-Wpointer-arith -Waggregate-return -Wnested-externs $CFLAGS"
fi
CFLAGS="-Wall -g -DYYDEBUG $CFLAGS"
YFLAGS="-v -d"
if test x"$ac_cv_prog_LEX" = x"flex" ; then
LEX_FLAGS="--warn --debug"
fi
else
for flag in $DESIRED_FLAGS; do
AS_COMPILER_FLAG([$flag], [CFLAGS="$CFLAGS $flag"])
done
dnl No debugging information, include the optimizations
CFLAGS="-O2 -DNDEBUG $CFLAGS"
YFLAGS="-d"
fi
dnl Disable debugging if it's not specified
if test x"$debug_enabled" != x"yes" ; then
CFLAGS="-DNDEBUG $CFLAGS"
dnl
dnl Make sure we can actually handle the "--with-*" and "--enable-*" stuff.
dnl
dnl Handle the SOCKS support
if test x"$socks_enabled" = x"yes"; then
if test x"$socks_header" = x"yes" -a x"$socks_library" = x"yes"; then
CFLAGS="-I/usr/include/sock.h -DSOCKS $CFLAGS"
LIBS="-lsocks $LIBS"
else
AC_MSG_ERROR([Could not include the SOCKS library or header])
fi
fi
dnl Handle the REGEX library
if test x"$ac_cv_func_regexec" != x"yes"; then
dnl We don't have a functioning REGEX so include our copy
tinyproxy_use_our_regex=yes
else
AC_MSG_CHECKING([whether the system's regex library is broken])
AC_CACHE_VAL(tinyproxy_cv_regex_broken,
[AC_TRY_RUN([
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#if HAVE_REGEX_H
# include <regex.h>
#endif
int main(void)
{
regex_t blah;
if (regcomp(&blah, "foo.*bar", REG_NOSUB) != 0)
exit(1);
if (regexec(&blah, "foobar", 0, NULL, 0) != 0)
exit(1);
else
exit(0);
return 0;
}
],
tinyproxy_cv_regex_broken=no,
tinyproxy_cv_regex_broken=yes,
tinyproxy_cv_regex_broken=yes)])
AC_MSG_RESULT([$tinyproxy_cv_regex_broken])
if test x"$tinyproxy_cv_regex_broken" = x"yes" ; then
AC_MSG_NOTICE([Using the included GNU regex instead.])
tinyproxy_use_our_regex=yes
fi
fi
AH_TEMPLATE([USE_GNU_REGEX],
[Defined if you want to use the included regex routines.])
if test x"$tinyproxy_use_our_regex" = x"yes" ; then
AC_DEFINE(USE_GNU_REGEX)
ADDITIONAL_OBJECTS="$ADDITIONAL_OBJECTS gnuregex.o"
fi
dnl
dnl Substitute the variables into the various Makefiles
dnl
# runstatedir isn't available for Autoconf < 2.70
AS_IF([test -z "${runstatedir}"], [runstatedir='${localstatedir}/run'])
AC_SUBST([runstatedir])
AC_SUBST(CFLAGS)
AC_SUBST(LDFLAGS)
AC_SUBST(YFLAGS)
AC_SUBST(CPPFLAGS)
AC_SUBST(LEX_FLAGS)
AC_SUBST(LIBS)
AC_SUBST(ADDITIONAL_OBJECTS)
AC_SUBST(TINYPROXY_CONFIG_DIR)
AC_SUBST(TINYPROXY_CONFIG_FILE)
if test x"$manpage_support_enabled" = x"yes"; then
AC_PATH_PROG(POD2MAN, pod2man, no)
if test "x$POD2MAN" = "xno" && \
! test -e docs/man5/tinyproxy.conf.5 -a -e docs/man8/tinyproxy.8 ; then
AC_MSG_ERROR([
manpage generation requested, but neither pod2man
nor pre-generated manpages found.
Use --disable-manpage-support if you want to compile anyway.])
fi
fi #manpage_support_enabled
AM_CONDITIONAL(HAVE_POD2MAN, test "x$POD2MAN" != "x" -a "x$POD2MAN" != "xno")
AC_PATH_PROG(GPERF, gperf, no)
AH_TEMPLATE([HAVE_GPERF],
[Whether you have gperf installed for faster config parsing.])
tmp_gperf=false
if test "x$GPERF" != "x" -a "x$GPERF" != "xno" ; then
AS_ECHO_N(["checking whether gperf is recent enough... "])
if "$GPERF" < src/conf-tokens.gperf >/dev/null 2>&1 ; then
AS_ECHO("yes")
AC_DEFINE(HAVE_GPERF)
tmp_gperf=true
else
AS_ECHO("no")
fi
fi
AM_CONDITIONAL(HAVE_GPERF, $tmp_gperf)
AC_CONFIG_FILES([
Makefile
src/Makefile
data/Makefile
data/templates/Makefile
etc/Makefile
docs/Makefile
docs/man5/Makefile
docs/man5/tinyproxy.conf.txt
docs/man8/Makefile
m4macros/Makefile
tests/Makefile
tests/scripts/Makefile
scripts/Makefile
])
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile packaging/Makefile packaging/fedora/Makefile packaging/fedora/tinyproxy.spec])
AC_OUTPUT
# the manpages are shipped in the release tarball and we don't want them to
# get regenerated if pod2man is not available. the intermediate files from
# AC_CONFIG_FILES are created with config.status, which is created at configure
# runtime, so we need to touch them after config.status terminated to prevent
# make from rebuild them.
if test "x$POD2MAN" = "xno" ; then
touch docs/man5/tinyproxy.conf.txt
touch docs/man8/tinyproxy.txt
if test -e docs/man5/tinyproxy.conf.5 ; then
touch docs/man5/tinyproxy.conf.5
fi
if test -e docs/man8/tinyproxy.8 ; then
touch docs/man8/tinyproxy.8
fi
fi
if test "x$HAVE_GPERF" = "xno" && test -e src/conf-tokens-gperf.inc ; then
touch src/conf-tokens-gperf.inc
fi

View File

@ -1,2 +0,0 @@
SUBDIRS = \
templates

View File

@ -1,12 +0,0 @@
templatesdir = $(pkgdatadir)
TEMPLATES = \
debug.html \
default.html \
stats.html
templates_DATA = \
$(TEMPLATES)
EXTRA_DIST = \
$(TEMPLATES)

View File

@ -1,53 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>{errno} {cause}</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>{cause}</h1>
<p>{detail}</p>
<p>Here are the error variables:</p>
<dl>
<dt>request</dt>
<dd>{request}</dd>
<dt>cause</dt>
<dd>{cause}</dd>
<dt>clientip</dt>
<dd>{clientip}</dd>
<dt>clienthost</dt>
<dd>{clienthost}</dd>
<dt>package</dt>
<dd>{package}</dd>
<dt>date</dt>
<dd>{date}</dd>
<dt>detail</dt>
<dd>{detail}</dd>
<dt>url</dt>
<dd>{url}</dd>
</dl>
<hr />
<p><em>Generated by <a href="{website}">{package}</a>.</em></p>
</body>
</html>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>{errno} {cause}</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>{cause}</h1>
<p>{detail}</p>
<hr />
<p><em>Generated by <a href="{website}">{package}</a>.</em></p>
</body>
</html>

View File

@ -1,95 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Stats [{package}]</title>
<meta charset="UTF-8" />
<style type="text/css">
body {
color: #eee;
background: #110d0d;
text-align: center;
font: 12pt/1.6 Open Sans, Segoe UI, sans-serif;
}
#container {
position: absolute;
top: 0;
left: 0;
margin: 0;
width: 100%;
height: 100%;
display: table;
}
#inner {
width: 100%;
display: table-cell;
vertical-align: middle;
}
table {
width: auto;
margin: auto;
height: auto;
background: #222020;
border: 1px solid #777373;
border-spacing: 3px;
}
th,
td {
padding: 6px 18px;
}
th {
font-weight: 700;
background: linear-gradient(to bottom, #777373, #555151);
}
.odd {
background: #444040;
}
.even {
background: #555151;
}
.center {
text-align: center;
}
.right {
text-align: right;
font-weight: 600;
}
</style>
</head>
<body>
<div id="container">
<div id="inner">
<table>
<tr>
<th colspan="2">{package} statistics</th>
</tr>
<tr class="odd">
<td class="right">Open connections</td>
<td class="center">{opens}</td>
</tr>
<tr class="even">
<td class="right">Bad connections</td>
<td class="center">{badconns}</td>
</tr>
<tr class="odd">
<td class="right">Denied connections</td>
<td class="center">{deniedconns}</td>
</tr>
<tr class="even">
<td class="right">Refused (high load)</td>
<td class="center">{refusedconns}</td>
</tr>
<tr class="odd">
<td class="right">Total requests</td>
<td class="center">{reqs}</td>
</tr>
</table>
</div>
</div>
</body>
</html>

15
doc/HTML_VARIABLES Normal file
View File

@ -0,0 +1,15 @@
There are several standard HTML variables that are available in every .html
file:
request - The full HTTP request line.
cause - The abbreviated cause of the error condition.
clientip - The IP address of the client making the request.
clienthost - The hostname of the client making the request.
version - The version of tinyproxy.
package - Presently, resolves to 'tinyproxy'.
date - The current date/time in HTTP format.
In addition, almost all pages support:
detail - A detailed, plain English explanation of the error and possible
causes. You might consider this the Microsoftian error message.

22
doc/Makefile.am Normal file
View File

@ -0,0 +1,22 @@
# HTML Variable Substitution Files
HTML_VAR_SUBST = HTML_VARIABLES debug.html default.html stats.html
man_MANS = tinyproxy.8
EXTRA_DIST = $(man_MANS) tinyproxy.conf \
HTTP_ERROR_CODES RFC_INFO \
filter-howto.txt \
report.sh.tmpl \
$(HTML_VAR_SUBST)
install-exec-local: report.sh
# Build the report.sh script
report.sh: $(srcdir)/report.sh.tmpl
sed -e "s,@TINYPROXY_LOCATION@,$(DESTDIR)$(sbindir)," < $(srcdir)/report.sh.tmpl > $(top_builddir)/doc/report.sh
chmod 755 $(top_builddir)/doc/report.sh
@echo ""
@echo "Report tinyproxy"
@echo "----------------"
@echo "Run the $(top_builddir)/doc/report.sh script to report a"
@echo "successful installation to the authors."
@echo ""

48
doc/debug.html Normal file
View File

@ -0,0 +1,48 @@
<html>
<head>
<title>
Request failed - {cause}
</title>
</head>
<body>
<center>{cause}</center>
<blockquote>
The request you made failed. Here are the error variables:
<dt>
request
<dd>
{request}
<dt>
cause
<dd>
{cause}
<dt>
clientip
<dd>
{clientip}
<dt>
clienthost
<dd>
{clienthost}
<dt>
version
<dd>
{version}
<dt>
package
<dd>
{package}
<dt>
date
<dd>
{date}
<dt>
detail
<dd>
{detail}
<dt>
url
<dd>
{url}
</body>
</html>

7
doc/default.html Normal file
View File

@ -0,0 +1,7 @@
<html><head><title>{cause}</title></head>
<body>
<font size=\+2\>Cache Error!</font><br>
The following error has occured: {detail}
<hr>
<font size=\-1\><em>Generated by {package} ({version})</em></font>
</body></html>

52
doc/filter-howto.txt Normal file
View File

@ -0,0 +1,52 @@
Using tinyproxy with Your Home/Small Business Network
Written: Patrick L. McGillan
Edited: Robert James Kaes (2002-06-04)
-----------------------------------------------------
Being as this will be the most common usage and there were no clear
basic instructions for this scenario, I thought I would write up what
I did for my home system.
First the layout of the network. A cable modem is connected through a
Linksys Router to a small hub. The computers hanging off the hub and
have a clear shot to the Internet.
So, the connection from the Internet to the hub looks like this:
Internet->Cable TV Line->Cable Modem->Linksys Router->Hub/Switch
Restricting Internet web access on some of those computers (connected
to the hub) is what using tinyproxy is all about. Using the web
interface to the Linksys router, turn off all Internet access to those
computers that shouldn't have direct access to the Internet. This is
done by clicking on the advanced tab and entering the IP number in the
filter range. Now those computers have to go through a proxy, for
their access, as they have no direct access.
On one of the Linux computers which still has Internet access (I use
an old 486) load up tinyproxy. Now have the users configure their
Internet Explorer/Netscape Navigator programs to use the proxy on the
tinyproxy computer box, along with the port number declared in the
tinyproxy configuration file. By default, there is no blocking of web
sites with this program, so I created a file, called "filter", to
start blocking some sites.
Example "filter" file entries:
bannerads.zwire.com
ad.doubleclick.net
ads.fortunecity.com
This filter file usually goes into the same folder, as your
configuration file. Be sure and uncomment the 'Filter' line in your
configuration file and make sure it points at your newly created
filter file.
------------------------------------------------------------------------
Copyright (c) 2002 Patrick L. McGillan <pmcgillan@dwx.com>
This document is released under the same copyright license as
tinyproxy. You should have found a COPYING file in the top level
directory of this distribution which contains the current license.

16
doc/report.sh.tmpl Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
TINYPROXY_BIN=@TINYPROXY_LOCATION@/tinyproxy
(echo "date: "
date
echo "uname: "
uname -a
echo "ps: "
ps -ef | grep '[t]inyproxy'
echo "ver: "
if [ -x $TINYPROXY_BIN ]; then
$TINYPROXY_BIN -v
else
echo no ver available.
fi;) 2>&1 | mail -s 'tinyproxy install report' rjkaes@users.sourceforge.net

10
doc/stats.html Normal file
View File

@ -0,0 +1,10 @@
<html><head><title>{package} ({version}) stats</title></head>
<body>
<center><h2>{package} ({version}) run-time statistics</h2></center><hr>
<blockquote>
Number of open connections: {opens}<br>
Number of requests: {reqs}<br>
Number of bad connections: {badconns}<br>
Number of denied connections: {deniedconns}<br>
Number of refused connections due to high load: {refusedconns}<br>
</blockquote></body></html>

60
doc/tinyproxy.8 Normal file
View File

@ -0,0 +1,60 @@
.\" -*- nroff -*-
.\"
.\" tinyproxy.8
.\"
.\" Copyright (c) 1998-2000 Steven Young and Robert James Kaes.
.\" Copyright (c) 2001 Robert James Kaes
.\"
.\" This program is distributed under the terms of the GNU General Public
.\" License. See COPYING for additional information.
.\"
.TH tinyproxy 8 .\" "tinyproxy Manual" "January 27, 2003"
.SH NAME
tinyproxy - A small HTTP proxy server
.SH SYNTAX
\fBtinyproxy\fR [ \fBoptions\fR ]
.SH VERSION
This man page documents tinyproxy
.SH DESCRIPTION
\fBtinyproxy\fR is an HTTP proxy server designed to consume a minimum of
system resources. It listens on a given TCP port and handles HTTP proxy
requests.
.SH OPTIONS
.IP "-c config_file"
Use an alternate configuration file.
.IP -d
Don't daemonize; stay in the foreground. Useful for debugging purposes.
.IP -h
Display a short help screen of command line arguments and exit.
.IP -l
Displays the licensing agreement.
.IP -v
Display version information and exit.
.SH SIGNALS
In addition to these command line options, there are also several signals
that can be sent to tinyproxy while it is running to generate debugging
information and to force certain events.
.TP 5
.B SIGHUP
Force \fBtinyproxy\fR to do a garbage collection on the current connections
linked list. This is usually done automatically after a certain number of
connections have been handled.
.SH FILES
.nf
/etc/tinyproxy/tinyproxy.conf
/var/run/tinyproxy.pid
/var/log/tinyproxy.log
.fi
.SH AUTHORS
.nf
Robert James Kaes (rjkaes@flarenet.com)
Steven Young (sdyoung@users.sourceforge.net)
.fi
.SH COPYRIGHT
\fBtinyproxy\fR is distributed under the GNU Public License (GPL). For more
information on the GPL, please see the file COPYING which should have been
included in the archive with \fBtinyproxy\fR. Failing that,
http://www.fsf.org/ will doubtless have a copy up for you to peruse. Please
don't use this software if you don't agree to the terms specified therein.
.SH AVAILABILITY
The latest version of \fBtinyproxy\fR can be acquired from: http://tinyproxy.sourceforge.net/

228
doc/tinyproxy.conf Normal file
View File

@ -0,0 +1,228 @@
##
## tinyproxy.conf -- tinyproxy daemon configuration file
##
#
# Name of the user the tinyproxy daemon should switch to after the port
# has been bound.
#
User nobody
Group nogroup
#
# Port to listen on.
#
Port 8888
#
# If you have multiple interfaces this allows you to bind to only one. If
# this is commented out, tinyproxy will bind to all interfaces present.
#
#Listen 192.168.0.1
#
# The Bind directive allows you to bind the outgoing connections to a
# particular IP address.
#
#Bind 192.168.0.1
#
# Timeout: The number of seconds of inactivity a connection is allowed to
# have before it closed by tinyproxy.
#
Timeout 600
#
# ErrorFile: Defines the HTML file to send when a given HTTP error
# occurs. You will probably need to customize the location to your
# particular install. The usual locations to check are:
# /usr/local/share/tinyproxy
# /usr/share/tinyproxy
# /etc/tinyproxy
#
# ErrorFile 404 "/usr/share/tinyproxy/404.html"
# ErrorFile 400 "/usr/share/tinyproxy/400.html"
# ErrorFile 503 "/usr/share/tinyproxy/503.html"
# ErrorFile 403 "/usr/share/tinyproxy/403.html"
# ErrorFile 408 "/usr/share/tinyproxy/408.html"
#
# DefaultErrorFile: The HTML file that gets sent if there is no
# HTML file defined with an ErrorFile keyword for the HTTP error
# that has occured.
#
DefaultErrorFile "/usr/share/tinyproxy/default.html"
#
# StatFile: The HTML file that gets sent when a request is made
# for the stathost. If this file doesn't exist a basic page is
# hardcoded in tinyproxy.
#
StatFile "/usr/share/tinyproxy/stats.html"
#
# Where to log the information. Either LogFile or Syslog should be set,
# but not both.
#
Logfile "/var/log/tinyproxy.log"
# Syslog On
#
# Set the logging level. Allowed settings are:
# Critical (least verbose)
# Error
# Warning
# Notice
# Connect (to log connections without Info's noise)
# Info (most verbose)
# The LogLevel logs from the set level and above. For example, if the LogLevel
# was set to Warning, than all log messages from Warning to Critical would be
# output, but Notice and below would be suppressed.
#
LogLevel Info
#
# PidFile: Write the PID of the main tinyproxy thread to this file so it
# can be used for signalling purposes.
#
PidFile "/var/run/tinyproxy.pid"
#
# Include the X-Tinyproxy header, which has the client's IP address when
# connecting to the sites listed.
#
#XTinyproxy mydomain.com
#
# Turns on upstream proxy support.
#
# The upstream rules allow you to selectively route upstream connections
# based on the host/domain of the site being accessed.
#
# For example:
# # connection to test domain goes through testproxy
# upstream testproxy:8008 ".test.domain.invalid"
# upstream testproxy:8008 ".our_testbed.example.com"
# upstream testproxy:8008 "192.168.128.0/255.255.254.0"
#
# # no upstream proxy for internal websites and unqualified hosts
# no upstream ".internal.example.com"
# no upstream "www.example.com"
# no upstream "10.0.0.0/8"
# no upstream "192.168.0.0/255.255.254.0"
# no upstream "."
#
# # connection to these boxes go through their DMZ firewalls
# upstream cust1_firewall:8008 "testbed_for_cust1"
# upstream cust2_firewall:8008 "testbed_for_cust2"
#
# # default upstream is internet firewall
# upstream firewall.internal.example.com:80
#
# The LAST matching rule wins the route decision. As you can see, you
# can use a host, or a domain:
# name matches host exactly
# .name matches any host in domain "name"
# . matches any host with no domain (in 'empty' domain)
# IP/bits matches network/mask
# IP/mask matches network/mask
#
#Upstream some.remote.proxy:port
#
# This is the absolute highest number of threads which will be created. In
# other words, only MaxClients number of clients can be connected at the
# same time.
#
MaxClients 100
#
# These settings set the upper and lower limit for the number of
# spare servers which should be available. If the number of spare servers
# falls below MinSpareServers then new ones will be created. If the number
# of servers exceeds MaxSpareServers then the extras will be killed off.
#
MinSpareServers 5
MaxSpareServers 20
#
# Number of servers to start initially.
#
StartServers 10
#
# MaxRequestsPerChild is the number of connections a thread will handle
# before it is killed. In practise this should be set to 0, which disables
# thread reaping. If you do notice problems with memory leakage, then set
# this to something like 10000
#
MaxRequestsPerChild 0
#
# The following is the authorization controls. If there are any access
# control keywords then the default action is to DENY. Otherwise, the
# default action is ALLOW.
#
# Also the order of the controls are important. The incoming connections
# are tested against the controls based on order.
#
Allow 127.0.0.1
Allow 192.168.1.0/25
#
# The "Via" header is required by the HTTP RFC, but using the real host name
# is a security concern. If the following directive is enabled, the string
# supplied will be used as the host name in the Via header; otherwise, the
# server's host name will be used.
#
ViaProxyName "tinyproxy"
#
# The location of the filter file.
#
#Filter "/etc/tinyproxy/filter"
#
# Filter based on URLs rather than domains.
#
#FilterURLs On
#
# Use POSIX Extended regular expressions rather than basic.
#
#FilterExtended On
#
# Use case sensitive regular expressions.
#
#FilterCaseSensitive On
#
# Change the default policy of the filtering system. If this directive is
# commented out, or is set to "No" then the default policy is to allow
# everything which is not specifically denied by the filter file.
#
# However, by setting this directive to "Yes" the default policy becomes to
# deny everything which is _not_ specifically allowed by the filter file.
#
#FilterDefaultDeny Yes
#
# If an Anonymous keyword is present, then anonymous proxying is enabled.
# The headers listed are allowed through, while all others are denied. If
# no Anonymous keyword is present, then all header are allowed through.
# You must include quotes around the headers.
#
#Anonymous "Host"
#Anonymous "Authorization"
#
# This is a list of ports allowed by tinyproxy when the CONNECT method
# is used. To disable the CONNECT method altogether, set the value to 0.
# If no ConnectPort line is found, all ports are allowed (which is not
# very secure.)
#
# The following two ports are used by SSL.
#
ConnectPort 443
ConnectPort 563

3
docs/.gitignore vendored
View File

@ -1,3 +0,0 @@
Makefile
Makefile.in
report.sh

View File

@ -1,8 +0,0 @@
SUBDIRS = \
man5 \
man8
EXTRA_DIST = \
http-error-codes.txt \
http-rfcs.txt

View File

@ -1,3 +0,0 @@
*.5
*.xml
*.txt

View File

@ -1,25 +0,0 @@
if HAVE_MANPAGE_INTEREST
MAN5_FILES = \
tinyproxy.conf.txt
endif
M_SECTION=5
M_NAME=TINYPROXY.CONF
man_MANS = \
$(MAN5_FILES:.txt=.5)
.txt.5:
if HAVE_POD2MAN
$(AM_V_GEN) $(POD2MAN) --center="Tinyproxy manual" \
--section=$(M_SECTION) --name=$(M_NAME) --release="Version @VERSION@" \
$< > $@
else
@echo "*** pod2man is required to regenerate $(@) ***"; exit 1;
endif
MAINTAINERCLEANFILES = \
$(MAN5_FILES:.txt=.5)
EXTRA_DIST = \
$(MAN5_FILES:.txt=.5)

View File

@ -1,440 +0,0 @@
=pod
=encoding utf8
=head1 NAME
tinyproxy.conf - Tinyproxy HTTP proxy daemon configuration file
=head1 SYNOPSIS
B<tinyproxy.conf>
=head1 DESCRIPTION
L<tinyproxy(8)> reads its configuration file, typically stored in
`/etc/tinyproxy/tinyproxy.conf` (or passed to Tinyproxy with -c on the
command line). This manpage describes the syntax and contents of the
configuration file.
The Tinyproxy configuration file contains key-value pairs, one per
line. Lines starting with `#` and empty lines are comments and are
ignored. Keywords are case-insensitive, whereas values are
case-sensitive. Some string values must be enclosed in double
quotes (") as noted below.
The possible keywords and their descriptions are as follows:
=over 4
=item B<User>
The user which the Tinyproxy process should run as, after the
initial port-binding has been done as the `root` user. Either the
user name or the UID may be specified.
=item B<Group>
The group which the Tinyproxy process should run as, after the
initial port-binding has been done as the `root` user. Either the
group name or the GID may be specified.
=item B<Port>
The port which the Tinyproxy service will listen on. If the port is
less than 1024, you will need to start the Tinyproxy process as the
`root` user.
=item B<Listen>
By default, Tinyproxy listens for connections on all available
interfaces (i.e. it listens on the wildcard address `0.0.0.0`).
With this configuration parameter, Tinyproxy can be told to listen
only on one specific address.
=item B<Bind>
This allows you to specify which address Tinyproxy will bind
to for outgoing connections.
This parameter may be specified multiple times, then Tinyproxy
will try all the specified addresses in order.
=item B<BindSame>
If this boolean parameter is set to `yes`, then Tinyproxy will
bind the outgoing connection to the IP address of the incoming
connection that triggered the outgoing request.
=item B<Timeout>
The maximum number of seconds of inactivity a connection is
allowed to have before it is closed by Tinyproxy.
=item B<ErrorFile>
This parameter controls which HTML file Tinyproxy returns when a
given HTTP error occurs. It takes two arguments, the error number
and the location of the HTML error file. Enclose the file location
in double quotes.
=item B<DefaultErrorFile>
The HTML template file returned when an error occurs for which no
specific error file has been set. Enclose in double quotes.
=item B<StatHost>
The host name or IP address that is treated as the `stat host`.
Enclose in double quotes. Whenever Tinyproxy receives a request for
the `stat host` it returns an internal statistics page instead of
forwarding the request to that host. The template for this page can be
configured with the `StatFile` configuration option. The default value
of `StatHost` is `@TINYPROXY_STATHOST@`.
=item B<StatFile>
The HTML file that Tinyproxy sends in response to a request for the
`stat host`. Enclose in double quotes. If this parameter is not set,
Tinyproxy returns a hard-coded basic statistics page. See the STATHOST
section in the L<tinyproxy(8)> manual page for details.
Note that the StatFile and the error files configured with ErrorFile
and DefaultErrorFile are template files that can contain a few
template variables that Tinyproxy expands prior to delivery.
Examples are "{cause}" for an abbreviated error description and
"{detail}" for a detailed error message. The L<tinyproxy(8)>
manual page contains a description of all template variables.
=item B<LogFile>
The location of the file to which Tinyproxy writes its debug output.
Enclose in double quotes. Alternatively, Tinyproxy can log to syslog
-- see the Syslog option.
=item B<Syslog>
When set to `On`, this option tells Tinyproxy to write its
debug messages to syslog instead of to a log file configured
with `LogFile`. These two options are mutually exclusive.
=item B<LogLevel>
Sets the log level. Messages from the set level and above are
logged. For example, if the LogLevel was set to Warning, then all
log messages from Warning to Critical would be output, but Notice
and below would be suppressed. Allowed values are:
=over 4
=item * Critical (least verbose)
=item * Error
=item * Warning
=item * Notice
=item * Connect (log connections without Info's noise)
=item * Info (most verbose)
=back
=item B<PidFile>
The location of the file where the main Tinyproxy process stores its
process ID for signaling purposes. Enclose in double quotes.
=item B<XTinyproxy>
Setting this option to `Yes` tells Tinyproxy to add a header
`X-Tinyproxy` containing the client's IP address to the request.
=item B<Upstream>
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
host or domain of the site being accessed. The rules are stored
in the order encountered in the configuration file and the
LAST matching rule wins. The following forms for specifying upstream
rules exist:
=over 4
=item * I<upstream type host:port> turns proxy upstream support on generally.
=item * I<upstream type user:pass@host:port>
does the same, but uses the supplied credentials for authentication.
=item * I<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`.
a `site_spec` is either a full domain name, a domain name starting with a
`.`, in which case it is treated as a suffix, or an ip/mask tuple.
the `site_spec` needs to be double-quoted.
=item * I<upstream none "site_spec">
turns off upstream support for sites matching `site_spec`, that means the
connection is done directly.
=back
It's recommended to use raw IP addresses to specify the upstream host, so
no costly DNS lookup has to be done everytime it is used.
IPv6 addresses need to be enclosed in square brackets.
The site can be specified in various forms as a hostname, domain
name or as an IP range:
=over 4
=item * I<name> matches host exactly
=item * I<.name> matches any host in domain "name"
=item * I<.> matches any host with no domain (in 'empty' domain)
=item * I<IP/bits> matches network/mask
=item * I<IP/mask> matches network/mask
=back
Note that the upstream directive can also be used to null-route
a specific target domain/host, e.g.:
`upstream http 0.0.0.0:0 ".adserver.com"`
=item B<MaxClients>
Tinyproxy creates one thread for each connected client.
This options specifies the absolute highest number processes that
will be created. With other words, only MaxClients clients can be
connected to Tinyproxy simultaneously.
=item B<Allow>
=item B<Deny>
The `Allow` and `Deny` options provide a means to customize
which clients are allowed to access Tinyproxy. `Allow` and `Deny`
lines can be specified multiple times to build the access control
list for Tinyproxy. The order in the config file is important.
If there are no `Allow` or `Deny` lines, then all clients are
allowed. Otherwise, the default action is to deny access.
The argument to `Allow` or `Deny` can be a single IP address
of a client host, like `127.0.0.1`, an IP address range, like
`192.168.0.1/24` or a string that will be matched against the
end of the client host name, i.e, this can be a full host name
like `host.example.com` or a domain name like `.example.com` or
even a top level domain name like `.com`.
Note that by adding a rule using a host or domain name, a costly name
lookup has to be done for every new connection, which could slow down
the service considerably.
=item B<BasicAuth>
Configure HTTP "Basic Authentication" username and password
for accessing the proxy. If there are any entries specified,
access is only granted for authenticated users.
BasicAuth user password
=item B<BasicAuthRealm>
In case "BasicAuth" is configured, the "realm" information.
"Proxy Authentication Required" status http 407 "error-response" can be
customized.
- defaults in code to "Tinyproxy" (PACKAGE_NAME), if not configured.
=item B<AddHeader>
Configure one or more HTTP request headers to be added to outgoing
HTTP requests that Tinyproxy makes. Note that this option will not
work for HTTPS traffic, as Tinyproxy has no control over what
headers are exchanged.
AddHeader "X-My-Header" "Powered by Tinyproxy"
=item B<ViaProxyName>
RFC 2616 requires proxies to add a `Via` header to the HTTP
requests, but using the real host name can be a security
concern. If the `ViaProxyname` option is present, then its
string value will be used as the host name in the Via header.
Otherwise, the server's host name will be used. Enclose in double
quotes.
=item B<DisableViaHeader>
When this is set to yes, Tinyproxy does NOT add the `Via` header
to the requests. This virtually puts Tinyproxy into stealth mode.
Note that RFC 2616 requires proxies to set the `Via` header, so by
enabling this option, you break compliance.
Don't disable the `Via` header unless you know what you are doing...
=item B<Filter>
Tinyproxy supports filtering of web sites based on URLs or
domains. This option specifies the location of the file
containing the filter rules, one rule per line.
Rules are specified as POSIX basic regular expressions (BRE), unless
another FilterType is specified.
Comment lines start with a `#` character.
Example filter file contents:
# filter exactly cnn.com
^cnn\.com$
# filter all subdomains of cnn.com, but not cnn.com itself
.*\.cnn.com$
# filter any domain that has cnn.com in it, like xcnn.comfy.org
cnn\.com
# filter any domain that ends in cnn.com
cnn\.com$
# filter any domain that starts with adserver
^adserver
=item B<FilterType>
This option can be set to one of `bre`, `ere`, or `fnmatch`.
If `bre` is set, the rules specified in the filter file are matched
using POSIX basic regular expressions, when set to `ere`, using
POSIX extended regular expressions, and when set to `fnmatch` using
the `fnmatch` function as specified in the manpage `man 3p fnmatch`.
`fnmatch` matching is identical to what's used in the shell to match
filenames, so for example `*.google.com` matches everything that
ends with `.google.com`.
If you don't know what regular expressions are or you're using filter
lists from 3rd party sources, `fnmatch` is probably what you want.
It's also the fastest matching method of the three.
=item B<FilterURLs>
If this boolean option is set to `Yes` or `On`, filtering is
performed for URLs rather than for domains. The default is to
filter based on domains.
Note that filtering for URLs works only in plain HTTP scenarios.
Since HTTPS has become ubiquitous during the last years, this
will only work on a tiny fraction of websites, so it is
recommended not to use this option.
=item B<FilterExtended>
Deprecated. Use `FilterType ere` instead.
If this boolean option is set to `Yes`, then extended POSIX
regular expressions are used for matching the filter rules.
The default is to use basic POSIX regular expressions.
=item B<FilterCaseSensitive>
If this boolean option is set to `Yes`, then the filter rules
are matched in a case sensitive manner. The default is to
match case-insensitively, unfortunately.
If you set this to `Yes`, then your matching will be almost
twice as fast.
This setting affects only `bre` and `ere` FilterTypes, fnmatch
is always case sensitive.
=item B<FilterDefaultDeny>
The default filtering policy is to allow everything that is
not matched by a filtering rule. Setting `FilterDefaultDeny`
to `Yes` changes the policy do deny everything but the domains
or URLs matched by the filtering rules.
In other words, if set to `No` the Filter list acts as a
blacklist, if set to `Yes` as a whitelist.
=item B<Anonymous>
If an `Anonymous` keyword is present, then anonymous proxying
is enabled. The headers listed with `Anonymous` are allowed
through, while all others are denied. If no Anonymous keyword
is present, then all headers are allowed through. You must
include double quotes around the headers.
Most sites require cookies to be enabled for them to work correctly, so
you will need to allow cookies through if you access those sites.
Example:
Anonymous "Host"
Anonymous "Authorization"
Anonymous "Cookie"
=item B<ConnectPort>
This option can be used to specify the ports allowed for the
CONNECT method. If no `ConnectPort` line is found, then all
ports are allowed. To disable CONNECT altogether, include a
single ConnectPort line with a value of `0`.
=item B<ReversePath>
Configure one or more ReversePath directives to enable reverse proxy
support. With reverse proxying it's possible to make a number of
sites appear as if they were part of a single site.
If you uncomment the following two directives and run Tinyproxy
on your own computer at port 8888, you can access example.com,
using http://localhost:8888/example/.
ReversePath "/example/" "http://www.example.com/"
=item B<ReverseOnly>
When using Tinyproxy as a reverse proxy, it is STRONGLY
recommended that the normal proxy is turned off by setting
this boolean option to `Yes`.
=item B<ReverseMagic>
Setting this option to `Yes`, makes Tinyproxy use a cookie to
track reverse proxy mappings. If you need to reverse proxy
sites which have absolute links you must use this option.
=item B<ReverseBaseURL>
The URL that is used to access this reverse proxy. The URL is
used to rewrite HTTP redirects so that they won't escape the
proxy. If you have a chain of reverse proxies, you'll need to
put the outermost URL here (the address which the end user
types into his/her browser). If this option is not set then
no rewriting of redirects occurs.
=back
=head1 BUGS
To report bugs in Tinyproxy, please visit
L<https://tinyproxy.github.io/>.
=head1 SEE ALSO
L<tinyproxy(8)>
=head1 AUTHOR
This manpage was written by the Tinyproxy project team.
=head1 COPYRIGHT
Copyright (c) 1998-2024 the Tinyproxy authors.
This program is distributed under the terms of the GNU General Public
License version 2 or above. See the COPYING file for additional
information.

View File

@ -1,3 +0,0 @@
*.8
*.xml
*.txt

View File

@ -1,36 +0,0 @@
if HAVE_MANPAGE_INTEREST
MAN8_FILES = \
tinyproxy.txt
endif
M_SECTION=8
M_NAME=TINYPROXY
man_MANS = \
$(MAN8_FILES:.txt=.8)
edit = sed \
-e 's|@localstatedir[@]|$(localstatedir)|g' \
-e 's|@runstatedir[@]|$(runstatedir)|g' \
-e 's|@sysconfdir[@]|$(sysconfdir)|g' \
-e 's|@TINYPROXY_STATHOST[@]|$(TINYPROXY_STATHOST)|g'
tinyproxy.txt: $(top_srcdir)/docs/man8/tinyproxy.txt.in Makefile
@rm -f $@ $@.tmp
$(AM_V_GEN) $(edit) $(top_srcdir)/docs/man8/$@.in > $@.tmp
@mv $@.tmp $@
.txt.8:
if HAVE_POD2MAN
$(AM_V_GEN) $(POD2MAN) --center="Tinyproxy manual" \
--section=$(M_SECTION) --name=$(M_NAME) --release="Version @VERSION@" \
$< > $@
else
@echo "*** pod2man is required to regenerate $(@) ***"; exit 1;
endif
MAINTAINERCLEANFILES = \
$(MAN8_FILES:.txt=.8)
EXTRA_DIST = \
$(MAN8_FILES:.txt=.8)

View File

@ -1,187 +0,0 @@
=pod
=encoding utf8
=head1 NAME
tinyproxy - A light-weight HTTP proxy daemon
=head1 SYNOPSIS
B<tinyproxy> [-vdch]
=head1 DESCRIPTION
B<tinyproxy> is a light-weight HTTP proxy daemon designed to consume a
minimum amount of system resources. It listens on a given TCP port and
handles HTTP proxy requests. Designed from the ground up to be fast and
yet small, it is an ideal solution for use cases such as embedded
deployments where a full featured HTTP proxy is required, but the system
resources for a larger proxy are unavailable.
=head1 OPTIONS
B<tinyproxy> accepts the following options:
=over 4
=item B<-c <config-file>>
Use an alternate configuration file.
=item B<-d>
Don't daemonize and stay in the foreground. Useful for debugging purposes.
=item B<-h>
Display a short help screen of command line arguments and exit.
=item B<-v>
Display version information and exit.
=back
=head1 SIGNALS
In addition to command-line options, there are also several signals that
can be sent to B<tinyproxy> while it is running to generate debugging
information and to force certain events.
=over 4
=item B<SIGHUP>
Force Tinyproxy to do a garbage collection on the current
connections linked list. This is usually done automatically after a
certain number of connections have been handled.
(Daemon mode only)
=item B<SIGUSR1>
Force reload of config file and filter list.
This is handy to update the configuration if Tinyproxy is running
in foreground without dropping active connections.
=back
=head1 TEMPLATE FILES
There are two occasions when Tinyproxy delivers HTML pages to
the client on it's own right:
=over 4
=item * When an error occurred, a corresponding error page is returned.
=item * When a request for the stathost is made, a page summarizing the
connection statistics is returned. (See STATHOST below.)
=back
The layout of both error pages and the statistics page can be
controlled via configurable HTML template files that are plain
HTML files that additionally understand a few template
variables.
=head1 TEMPLATE VARIABLES
There are several standard HTML variables that are available in every
template file:
=over 4
=item B<request>
The full HTTP request line.
=item B<cause>
The abbreviated cause of the error condition.
=item B<clientip>
The IP address of the client making the request.
=item B<clienthost>
The hostname of the client making the request.
=item B<version>
The version of Tinyproxy.
=item B<package>
The package name. Presently, resolves to 'tinyproxy'.
=item B<date>
The current date/time in HTTP format.
=back
In addition, almost all templates support:
=over 4
=item B<detail>
A detailed, plain English explanation of the error and possible
causes.
=back
When Tinyproxy finds a variable name enclosed in braces, e.g.
"{request}", then this is replaced by the value of the corresponding
variable before delivery of the page.
=head1 STATHOST
Tinyproxy returns a HTML page with connection statistics when it
receives a HTTP request for a certain host -- the stathost. The
stathost name defaults to `@TINYPROXY_STATHOST@` and can be changed at
runtime to any name or IP address with the configuration variable
`StatHost`.
The stat file template can be changed at runtime through the
configuration variable `StatFile`.
=head1 FILES
F<@sysconfdir@/tinyproxy/tinyproxy.conf>
F<@runstatedir@/tinyproxy/tinyproxy.pid>
F<@localstatedir@/log/tinyproxy/tinyproxy.log>
=head1 BUGS
To report bugs in Tinyproxy, please visit
L<https://tinyproxy.github.io/>.
=head1 SEE ALSO
L<tinyproxy.conf(5)>
=head1 AUTHOR
This manpage was written by the Tinyproxy project team.
=head1 COPYRIGHT
Copyright (c) 1998-2020 the Tinyproxy authors.
This program is distributed under the terms of the GNU General Public
License version 2 or above. See the COPYING file for additional
information.

View File

@ -1,15 +0,0 @@
# test webpage with `python -m SimpleHTTPServer`
all: index.html
tp.html.conf: ../man5/tinyproxy.conf.txt
pod2html --noindex < $^ | awk -f podhtml-filter.awk > $@
index.html: tp.html.head tp.html.conf tp.html.foot
cat $^ > $@
clean:
rm tp.html.conf index.html *.tmp
.PHONY: all clean

View File

@ -1,5 +0,0 @@
BEGIN {i=0}
/<\/{0,1}h1/ {if(!i)i=1; gsub("h1", "h4", $0);}
#/<\/body>/ {i=0;}
/BUGS/ {i=-1}
{if(i==1) print;}

View File

@ -1,426 +0,0 @@
/*******************************************************************************
Slate Theme for GitHub Pages
by Jason Costello, @jsncostello
*******************************************************************************/
@import url(github-light.css);
/*******************************************************************************
MeyerWeb Reset
*******************************************************************************/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
ol, ul {
list-style: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
/*******************************************************************************
Theme Styles
*******************************************************************************/
body {
box-sizing: border-box;
color:#373737;
background: #212121;
font-size: 16px;
font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4, h5, h6 {
margin: 10px 0;
font-weight: 700;
color:#222222;
font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif;
letter-spacing: -1px;
}
h1 {
font-size: 36px;
font-weight: 700;
}
h2 {
padding-bottom: 10px;
font-size: 32px;
background: url('../images/bg_hr.png') repeat-x bottom;
}
h3 {
font-size: 24px;
}
h4 {
font-size: 21px;
}
h5 {
font-size: 18px;
}
h6 {
font-size: 16px;
}
p {
margin: 10px 0 15px 0;
}
footer p {
color: #f2f2f2;
}
a {
text-decoration: none;
color: #007edf;
text-shadow: none;
transition: color 0.5s ease;
transition: text-shadow 0.5s ease;
-webkit-transition: color 0.5s ease;
-webkit-transition: text-shadow 0.5s ease;
-moz-transition: color 0.5s ease;
-moz-transition: text-shadow 0.5s ease;
-o-transition: color 0.5s ease;
-o-transition: text-shadow 0.5s ease;
-ms-transition: color 0.5s ease;
-ms-transition: text-shadow 0.5s ease;
}
a:hover, a:focus {text-decoration: underline;}
footer a {
color: #F2F2F2;
text-decoration: underline;
}
em {
font-style: italic;
}
strong {
font-weight: bold;
}
img {
position: relative;
margin: 0 auto;
max-width: 739px;
padding: 5px;
margin: 10px 0 10px 0;
border: 1px solid #ebebeb;
box-shadow: 0 0 5px #ebebeb;
-webkit-box-shadow: 0 0 5px #ebebeb;
-moz-box-shadow: 0 0 5px #ebebeb;
-o-box-shadow: 0 0 5px #ebebeb;
-ms-box-shadow: 0 0 5px #ebebeb;
}
p img {
display: inline;
margin: 0;
padding: 0;
vertical-align: middle;
text-align: center;
border: none;
}
pre, code {
width: 100%;
color: #222;
background-color: #fff;
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
font-size: 14px;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
}
pre {
width: 100%;
padding: 10px;
margin-bottom: 20px;
box-shadow: 0 0 10px rgba(0,0,0,.1);
overflow: auto;
}
code {
padding: 3px;
margin: 0 3px;
box-shadow: 0 0 10px rgba(0,0,0,.1);
}
pre code {
display: block;
box-shadow: none;
}
blockquote {
color: #666;
margin-bottom: 20px;
padding: 0 0 0 20px;
border-left: 3px solid #bbb;
}
ul, ol, dl {
margin-bottom: 15px
}
ul {
list-style-position: inside;
list-style: disc;
padding-left: 20px;
}
ol {
list-style-position: inside;
list-style: decimal;
padding-left: 20px;
}
dl dt {
font-weight: bold;
}
dl dd {
padding-left: 20px;
/* font-style: italic; */
}
dl p {
padding-left: 20px;
/* font-style: italic; */
}
hr {
height: 1px;
margin-bottom: 5px;
border: none;
background: url('../images/bg_hr.png') repeat-x center;
}
table {
border: 1px solid #373737;
margin-bottom: 20px;
text-align: left;
}
th {
font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
padding: 10px;
background: #373737;
color: #fff;
}
td {
padding: 10px;
border: 1px solid #373737;
}
form {
background: #f2f2f2;
padding: 20px;
}
/*******************************************************************************
Full-Width Styles
*******************************************************************************/
.outer {
width: 100%;
}
.inner {
position: relative;
max-width: 640px;
padding: 20px 10px;
margin: 0 auto;
}
#forkme_banner {
display: block;
position: absolute;
top:0;
right: 10px;
z-index: 10;
padding: 10px 50px 10px 10px;
color: #fff;
background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%;
font-weight: 700;
box-shadow: 0 0 10px rgba(0,0,0,.5);
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
#header_wrap {
background: #212121;
background: -moz-linear-gradient(top, #373737, #212121);
background: -webkit-linear-gradient(top, #373737, #212121);
background: -ms-linear-gradient(top, #373737, #212121);
background: -o-linear-gradient(top, #373737, #212121);
background: linear-gradient(top, #373737, #212121);
}
#header_wrap .inner {
padding: 50px 10px 30px 10px;
}
#project_title {
margin: 0;
color: #fff;
font-size: 42px;
font-weight: 700;
text-shadow: #111 0px 0px 10px;
}
#project_tagline {
color: #fff;
font-size: 24px;
font-weight: 300;
background: none;
text-shadow: #111 0px 0px 10px;
}
#downloads {
position: absolute;
width: 210px;
z-index: 10;
bottom: -40px;
right: 0;
height: 70px;
background: url('../images/icon_download.png') no-repeat 0% 90%;
}
.zip_download_link {
display: block;
float: right;
width: 90px;
height:70px;
text-indent: -5000px;
overflow: hidden;
background: url(../images/sprite_download.png) no-repeat bottom left;
}
.tar_download_link {
display: block;
float: right;
width: 90px;
height:70px;
text-indent: -5000px;
overflow: hidden;
background: url(../images/sprite_download.png) no-repeat bottom right;
margin-left: 10px;
}
.zip_download_link:hover {
background: url(../images/sprite_download.png) no-repeat top left;
}
.tar_download_link:hover {
background: url(../images/sprite_download.png) no-repeat top right;
}
#main_content_wrap {
background: #f2f2f2;
border-top: 1px solid #111;
border-bottom: 1px solid #111;
}
#main_content {
padding-top: 40px;
}
#footer_wrap {
background: #212121;
}
/*******************************************************************************
Small Device Styles
*******************************************************************************/
@media screen and (max-width: 480px) {
body {
font-size:14px;
}
#downloads {
display: none;
}
.inner {
min-width: 320px;
max-width: 480px;
}
#project_title {
font-size: 32px;
}
h1 {
font-size: 28px;
}
h2 {
font-size: 24px;
}
h3 {
font-size: 21px;
}
h4 {
font-size: 18px;
}
h5 {
font-size: 14px;
}
h6 {
font-size: 12px;
}
code, pre {
min-width: 320px;
max-width: 480px;
font-size: 11px;
}
}

View File

@ -1,21 +0,0 @@
<h2>
<a id="support" class="anchor" href="#support" aria-hidden="true"><span class="octicon octicon-link"></span></a>Support</h2>
<ul>
<li>Feel free to report a new bug or suggest features via github issues.</li>
<li>Tinyproxy developers hang out in #tinyproxy on irc.libera.chat.</li>
</ul>
</section>
</div>
<!-- FOOTER -->
<div id="footer_wrap" class="outer">
<footer class="inner">
<p>Published with <a href="https://pages.github.com">GitHub Pages</a></p>
</footer>
</div>
</body>
</html>

View File

@ -1,98 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="description" content="Tinyproxy : lightweight http(s) proxy daemon">
<link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css">
<title>Tinyproxy</title>
</head>
<body>
<!-- HEADER -->
<div id="header_wrap" class="outer">
<header class="inner">
<a id="forkme_banner" href="https://github.com/tinyproxy">View on GitHub</a>
<h1 id="project_title">Tinyproxy</h1>
<h2 id="project_tagline">lightweight http(s) proxy daemon</h2>
</header>
</div>
<!-- MAIN CONTENT -->
<div id="main_content_wrap" class="outer">
<section id="main_content" class="inner">
<h1>
<a id="tinyproxy" class="anchor" href="#tinyproxy" aria-hidden="true"><span class="octicon octicon-link"></span></a>Tinyproxy</h1>
<p>Tinyproxy is a light-weight HTTP/HTTPS proxy daemon for POSIX operating systems. Designed from the ground up to be fast and yet small, it is an ideal solution for use cases such as embedded deployments where a full featured HTTP proxy is required, but the system resources for a larger proxy are unavailable.</p>
<p>Tinyproxy is distributed using the GNU GPL license (version 2 or above).</p>
<h2>
<a id="features" class="anchor" href="#features" aria-hidden="true"><span class="octicon octicon-link"></span></a>Features</h2>
<p>Tinyproxy has a <strong>small footprint</strong> and requires very little in the way of system resources. The memory footprint tends to be around 2 MB with glibc, and the CPU load increases linearly with the number of simultaneous connections (depending on the speed of the connection). Thus, Tinyproxy can be run on an older machine, or on a network appliance such as a Linux-based broadband router, without any noticeable impact on performance.</p>
<p>Tinyproxy requires only a <strong>minimal POSIX environment</strong> to build and operate. It can use additional libraries to add functionality though.</p>
<p>Tinyproxy allows forwarding of <strong>HTTPS connections</strong> without modifying traffic in any way through the <code>CONNECT</code> method (see the <code>ConnectPort</code> directive, which you should disable, unless you want to restrict the users).</p>
<p>Tinyproxy supports being configured as a <strong>transparent proxy</strong>, so that a proxy can be used without requiring any client-side configuration. You can also use it as a <strong>reverse proxy</strong> front-end to your websites.</p>
<p>Using the <code>AddHeader</code> directive, you can <strong>add/insert HTTP headers</strong> to outgoing traffic (HTTP only).</p>
<p>If you're looking to build a custom web proxy, Tinyproxy is <strong>easy to modify</strong> to your custom needs. The source is straightforward, adhering to the KISS principle. As such, it can be used as a foundation for anything you may need a web proxy to do.</p>
<p>Tinyproxy has <strong>privacy features</strong> which can let you configure which HTTP headers should be allowed through, and which should be blocked. This allows you to restrict both what data comes to your web browser from the HTTP server (e.g., cookies), and to restrict what data is allowed through from your web browser to the HTTP server (e.g., version information). Note that these features do not affect HTTPS connections.</p>
<p>Using the <strong>remote monitoring</strong> facility, you can access proxy statistics from afar, letting you know exactly how busy the proxy is.</p>
<p>You can configure Tinyproxy to <strong>control access</strong> by only allowing requests from a certain subnet, or from a certain interface, thus ensuring that random, unauthorized people will not be using your proxy.</p>
<p>With a bit of configuration (specifically, making Tinyproxy created files owned by a non-root user and running it on a port greater than 1024), Tinyproxy can be made to run without any special privileges, thus minimizing the chance of system compromise. In fact, it is <b>recommended</b> to run it as a regular/restricted user. Furthermore, it was designed with an eye towards preventing buffer overflows. The simplicity of the code ensures it remains easy to spot such bugs.</p>
<h2>
<a id="downloads" class="anchor" href="#downloads" aria-hidden="true"><span class="octicon octicon-link"></span></a>Downloads</h2>
<p>Note that many distributions ship horribly outdated versions of tinyproxy, therefore it is recommended to compile it from source.</p>
<ul>
<li>On Red Hat Enterprise Linux, or its derivatives such as CentOS, install Tinyproxy from the EPEL repository by running yum install tinyproxy.</li>
<li>On Fedora, install Tinyproxy by running yum install tinyproxy.</li>
<li>On Debian and derived distributions, run apt-get install tinyproxy to install Tinyproxy.</li>
<li>For openSUSE run: zypper in tinyproxy</li>
<li>Arch users can install the Tinyproxy package from the community repository. Run pacman -S tinyproxy to install it.</li>
<li>FreeBSD, OpenBSD or NetBSD users can use the pkg_add utility to install the tinyproxy package.</li>
<li>Mac OS X users can check MacPorts to see if the Tinyproxy port there is recent enough.</li>
</ul>
<p>If you feel that the Tinyproxy binary package in your operating system is not recent (likely), please contact the package maintainer for that particular operating system. If this fails, you can always compile the latest stable, or even better, the latest git master version, from source code.</p>
<p>We distribute Tinyproxy in source code form, and it has to be compiled in order to be used on your system. Please see the INSTALL file in the source code tree for build instructions. The current stable version of Tinyproxy is available on the <a href="https://github.com/tinyproxy/tinyproxy/releases">releases page</a>. The Tinyproxy NEWS file contains the release notes. You can verify the tarball using its PGP signature. You can also browse the older releases of Tinyproxy.</p>
<p>We use Git as the version control system for the Tinyproxy source code repository. To get a copy of the Tinyproxy repository, use the command:</p>
<p>git clone <a href="https://github.com/tinyproxy/tinyproxy.git">https://github.com/tinyproxy/tinyproxy.git</a></p>
<h2>
<a id="quickstart" class="anchor" href="#quickstart" aria-hidden="true"><span class="octicon octicon-link"></span></a>Quickstart</h2>
<p>The quickest way to get started is using a minimal config file like the below:</p>
<pre><code>
Port 8888
Listen 127.0.0.1
Timeout 600
Allow 127.0.0.1
</code></pre>
<p>And then simply run <code>tinyproxy -d -c tinyproxy.conf</code> as your current user. This starts tinyproxy in foreground mode with <code>tinyproxy.conf</code> as its config, while logging to stdout. Now, all programs supporting a HTTP proxy can use 127.0.0.1:8888 as a proxy. You can try it out using <code>http_proxy=127.0.0.1:8888 curl example.com</code>.</p>
<h2>
<a id="documentation" class="anchor" href="#documentation" aria-hidden="true"><span class="octicon octicon-link"></span></a>Documentation</h2>

1
etc/.gitignore vendored
View File

@ -1 +0,0 @@
tinyproxy.conf

View File

@ -1,26 +0,0 @@
pkgsysconfdir = $(sysconfdir)/$(PACKAGE)
pkgsysconf_DATA = \
tinyproxy.conf
EXTRA_DIST = \
tinyproxy.conf.in
edit = sed \
-e 's|@bindir[@]|$(bindir)|g' \
-e 's|@datadir[@]|$(datadir)|g' \
-e 's|@datarootdir[@]|$(datarootdir)|g' \
-e 's|@pkgsysconfdir[@]|$(pkgsysconfdir)|g' \
-e 's|@localstatedir[@]|$(localstatedir)|g' \
-e 's|@runstatedir[@]|$(runstatedir)|g' \
-e 's|@pkgdatadir[@]|$(pkgdatadir)|g' \
-e 's|@prefix[@]|$(prefix)|g' \
-e 's|@TINYPROXY_STATHOST[@]|$(TINYPROXY_STATHOST)|g'
tinyproxy.conf: $(top_srcdir)/etc/tinyproxy.conf.in Makefile
@rm -f $@ $@.tmp
$(AM_V_GEN) $(edit) $(top_srcdir)/etc/$@.in > $@.tmp
@mv $@.tmp $@
CLEANFILES = \
tinyproxy.conf

View File

@ -1,329 +0,0 @@
##
## tinyproxy.conf -- tinyproxy daemon configuration file
##
## This example tinyproxy.conf file contains example settings
## with explanations in comments. For decriptions of all
## parameters, see the tinyproxy.conf(5) manual page.
##
#
# User/Group: This allows you to set the user and group that will be
# used for tinyproxy after the initial binding to the port has been done
# as the root user. Either the user or group name or the UID or GID
# number may be used.
#
User nobody
Group nobody
#
# Port: Specify the port which tinyproxy will listen on. Please note
# that should you choose to run on a port lower than 1024 you will need
# to start tinyproxy using root.
#
Port 8888
#
# Listen: If you have multiple interfaces this allows you to bind to
# only one. If this is commented out, tinyproxy will bind to all
# interfaces present.
#
#Listen 192.168.0.1
#
# Bind: This allows you to specify which interface will be used for
# outgoing connections. This is useful for multi-home'd machines where
# you want all traffic to appear outgoing from one particular interface.
#
#Bind 192.168.0.1
#
# BindSame: If enabled, tinyproxy will bind the outgoing connection to the
# ip address of the incoming connection.
#
#BindSame yes
#
# Timeout: The maximum number of seconds of inactivity a connection is
# allowed to have before it is closed by tinyproxy.
#
Timeout 600
#
# ErrorFile: Defines the HTML file to send when a given HTTP error
# occurs. You will probably need to customize the location to your
# particular install. The usual locations to check are:
# /usr/local/share/tinyproxy
# /usr/share/tinyproxy
# /etc/tinyproxy
#
#ErrorFile 400 "@pkgdatadir@/400.html"
#ErrorFile 502 "@pkgdatadir@/502.html"
#ErrorFile 503 "@pkgdatadir@/503.html"
#ErrorFile 403 "@pkgdatadir@/403.html"
#ErrorFile 408 "@pkgdatadir@/408.html"
#
# DefaultErrorFile: The HTML file that gets sent if there is no
# HTML file defined with an ErrorFile keyword for the HTTP error
# that has occured.
#
DefaultErrorFile "@pkgdatadir@/default.html"
#
# StatHost: This configures the host name or IP address that is treated
# as the stat host: Whenever a request for this host is received,
# Tinyproxy will return an internal statistics page instead of
# forwarding the request to that host. The default value of StatHost is
# @TINYPROXY_STATHOST@.
#
#StatHost "@TINYPROXY_STATHOST@"
#
#
# StatFile: The HTML file that gets sent when a request is made
# for the stathost. If this file doesn't exist a basic page is
# hardcoded in tinyproxy.
#
StatFile "@pkgdatadir@/stats.html"
#
# LogFile: Allows you to specify the location where information should
# be logged to. If you would prefer to log to syslog, then disable this
# and enable the Syslog directive. These directives are mutually
# exclusive. If neither Syslog nor LogFile are specified, output goes
# to stdout.
#
#LogFile "@localstatedir@/log/tinyproxy/tinyproxy.log"
#
# Syslog: Tell tinyproxy to use syslog instead of a logfile. This
# option must not be enabled if the Logfile directive is being used.
# These two directives are mutually exclusive.
#
#Syslog On
#
# LogLevel: Warning
#
# Set the logging level. Allowed settings are:
# Critical (least verbose)
# Error
# Warning
# Notice
# Connect (to log connections without Info's noise)
# Info (most verbose)
#
# The LogLevel logs from the set level and above. For example, if the
# LogLevel was set to Warning, then all log messages from Warning to
# Critical would be output, but Notice and below would be suppressed.
#
LogLevel Info
#
# PidFile: Write the PID of the main tinyproxy thread to this file so it
# can be used for signalling purposes.
# If not specified, no pidfile will be written.
#
#PidFile "@runstatedir@/tinyproxy/tinyproxy.pid"
#
# XTinyproxy: Tell Tinyproxy to include the X-Tinyproxy header, which
# contains the client's IP address.
#
#XTinyproxy Yes
#
# Upstream:
#
# Turns on upstream proxy support.
#
# The upstream rules allow you to selectively route upstream connections
# 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:
# # connection to test domain goes through testproxy
# upstream http testproxy:8008 ".test.domain.invalid"
# upstream http testproxy:8008 ".our_testbed.example.com"
# 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
# upstream none ".internal.example.com"
# upstream none "www.example.com"
# upstream none "10.0.0.0/8"
# upstream none "192.168.0.0/255.255.254.0"
# upstream none "."
#
# # connection to these boxes go through their DMZ firewalls
# upstream http cust1_firewall:8008 "testbed_for_cust1"
# upstream http cust2_firewall:8008 "testbed_for_cust2"
#
# # default upstream is internet firewall
# 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
# can use a host, or a domain:
# name matches host exactly
# .name matches any host in domain "name"
# . matches any host with no domain (in 'empty' domain)
# IP/bits matches network/mask
# IP/mask matches network/mask
#
#Upstream http some.remote.proxy:port
#
# MaxClients: This is the absolute highest number of threads which will
# be created. In other words, only MaxClients number of clients can be
# connected at the same time.
#
MaxClients 100
#
# Allow: Customization of authorization controls. If there are any
# access control keywords then the default action is to DENY. Otherwise,
# the default action is ALLOW.
#
# The order of the controls are important. All incoming connections are
# tested against the controls based on order.
#
Allow 127.0.0.1
Allow ::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
# BasicAuthRealm : In case BasicAuth is configured, the "realm" information.
# "Proxy Authentication Required" status http 407 "error-response" can be
# customized.
#
# - defaults in code to "Tinyproxy" (PACKAGE_NAME), if not configured.
#BasicAuthRealm "Tinyproxy"
#
# AddHeader: Adds the specified headers to outgoing HTTP requests that
# Tinyproxy makes. Note that this option will not work for HTTPS
# traffic, as Tinyproxy has no control over what headers are exchanged.
#
#AddHeader "X-My-Header" "Powered by Tinyproxy"
#
# ViaProxyName: The "Via" header is required by the HTTP RFC, but using
# the real host name is a security concern. If the following directive
# is enabled, the string supplied will be used as the host name in the
# Via header; otherwise, the server's host name will be used.
#
ViaProxyName "tinyproxy"
#
# DisableViaHeader: When this is set to yes, Tinyproxy does NOT add
# the Via header to the requests. This virtually puts Tinyproxy into
# stealth mode. Note that RFC 2616 requires proxies to set the Via
# header, so by enabling this option, you break compliance.
# Don't disable the Via header unless you know what you are doing...
#
#DisableViaHeader Yes
#
# Filter: This allows you to specify the location of the filter file.
#
#Filter "@pkgsysconfdir@/filter"
#
# FilterURLs: Filter based on URLs rather than domains.
#
#FilterURLs On
#
# FilterType: Use bre (default), ere, or fnmatch for filtering.
#
#FilterType fnmatch
#
# FilterCaseSensitive: Use case sensitive regular expressions.
#
#FilterCaseSensitive On
#
# FilterDefaultDeny: Change the default policy of the filtering system.
# If this directive is commented out, or is set to "No" then the default
# policy is to allow everything which is not specifically denied by the
# filter file.
#
# However, by setting this directive to "Yes" the default policy becomes
# to deny everything which is _not_ specifically allowed by the filter
# file.
#
#FilterDefaultDeny Yes
#
# Anonymous: If an Anonymous keyword is present, then anonymous proxying
# is enabled. The headers listed are allowed through, while all others
# are denied. If no Anonymous keyword is present, then all headers are
# allowed through. You must include quotes around the headers.
#
# Most sites require cookies to be enabled for them to work correctly, so
# you will need to allow Cookies through if you access those sites.
#
#Anonymous "Host"
#Anonymous "Authorization"
#Anonymous "Cookie"
#
# ConnectPort: This is a list of ports allowed by tinyproxy when the
# CONNECT method is used. To disable the CONNECT method altogether, set
# the value to 0. If no ConnectPort line is found, all ports are
# allowed.
#
# The following two ports are used by SSL.
#
#ConnectPort 443
#ConnectPort 563
#
# Configure one or more ReversePath directives to enable reverse proxy
# support. With reverse proxying it's possible to make a number of
# sites appear as if they were part of a single site.
#
# If you uncomment the following two directives and run tinyproxy
# on your own computer at port 8888, you can access Google using
# http://localhost:8888/google/ and Wired News using
# http://localhost:8888/wired/news/. Neither will actually work
# until you uncomment ReverseMagic as they use absolute linking.
#
#ReversePath "/google/" "http://www.google.com/"
#ReversePath "/wired/" "http://www.wired.com/"
#
# When using tinyproxy as a reverse proxy, it is STRONGLY recommended
# that the normal proxy is turned off by uncommenting the next directive.
#
#ReverseOnly Yes
#
# Use a cookie to track reverse proxy mappings. If you need to reverse
# proxy sites which have absolute links you must uncomment this.
#
#ReverseMagic Yes
#
# The URL that's used to access this reverse proxy. The URL is used to
# rewrite HTTP redirects so that they won't escape the proxy. If you
# have a chain of reverse proxies, you'll need to put the outermost
# URL here (the address which the end user types into his/her browser).
#
# If not set then no rewriting occurs.
#
#ReverseBaseURL "http://localhost:8888/"

View File

@ -1,3 +0,0 @@
EXTRA_DIST = \
as-compiler-flag.m4 \
argenable.m4

View File

@ -1,19 +0,0 @@
dnl $Id: argenable.m4,v 1.1 2004-08-24 18:40:21 rjkaes Exp $
dnl
dnl Define a new AC_ARG_ENABLE like macro which handles invalid inputs
dnl correctly. The macro takes three arguments:
dnl 1) the option name (used like --enable-option)
dnl 2) the help string
dnl 3) the default value (either yes or no)
dnl
dnl This macro also defines on variable in the form "option_enabled"
dnl set to either "yes" or "no".
dnl
AC_DEFUN([TP_ARG_ENABLE],
[AC_ARG_ENABLE([$1],
AS_HELP_STRING([--enable-$1], [$2]),
[case "${enableval}" in
yes) $1_enabled=yes ;;
no) $1_enabled=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-$1]) ;;
esac],[$1_enabled=$3])])

View File

@ -1,64 +0,0 @@
dnl as-compiler-flag.m4 0.1.0
dnl autostars m4 macro for detection of compiler flags
dnl David Schleef <ds@schleef.org>
dnl Tim-Philipp Müller <tim centricular net>
dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
dnl Tries to compile with the given CFLAGS.
dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
dnl and ACTION-IF-NOT-ACCEPTED otherwise.
AC_DEFUN([AS_COMPILER_FLAG],
[
AC_MSG_CHECKING([to see if compiler understands $1])
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
CFLAGS="$save_CFLAGS"
if test "X$flag_ok" = Xyes ; then
$2
true
else
$3
true
fi
AC_MSG_RESULT([$flag_ok])
])
dnl AS_CXX_COMPILER_FLAG(CPPFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
dnl Tries to compile with the given CPPFLAGS.
dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
dnl and ACTION-IF-NOT-ACCEPTED otherwise.
AC_DEFUN([AS_CXX_COMPILER_FLAG],
[
AC_REQUIRE([AC_PROG_CXX])
AC_MSG_CHECKING([to see if c++ compiler understands $1])
save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $1"
AC_LANG_PUSH(C++)
AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
CPPFLAGS="$save_CPPFLAGS"
if test "X$flag_ok" = Xyes ; then
$2
true
else
$3
true
fi
AC_LANG_POP(C++)
AC_MSG_RESULT([$flag_ok])
])

5
packaging/Makefile.am Normal file
View File

@ -0,0 +1,5 @@
# The various packaging directories
SUBDIRS = fedora

1
packaging/fedora/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
tinyproxy.spec

View File

@ -0,0 +1,9 @@
# Packaging files
PACKAGING_FILES = \
tinyproxy.init \
tinyproxy.spec
EXTRA_DIST = $(PACKAGING_FILES)

View File

@ -0,0 +1,106 @@
#!/bin/sh
#
# tinyproxy Startup script for the tinyproxy server
#
# chkconfig: - 85 15
# description: small, efficient HTTP/SSL proxy daemon
#
# processname: tinyproxy
# config: /etc/tinyproxy/tinyproxy.conf
# config: /etc/sysconfig/tinyproxy
# pidfile: /var/run/tinyproxy.pid
#
# Note: pidfile is created by tinyproxy in its config
# see PidFile in the configuration file.
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
exec="/usr/sbin/tinyproxy"
prog=$(basename $exec)
config="/etc/tinyproxy/tinyproxy.conf"
[ -e /etc/sysconfig/tinyproxy ] && . /etc/sysconfig/tinyproxy
lockfile=/var/lock/subsys/tinyproxy
start() {
[ -x $exec ] || exit 5
[ -f $config ] || exit 6
echo -n $"Starting $prog: "
daemon $exec -c $config
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $"Stopping $prog: "
# stop it here, often "killproc $prog"
killproc $prog
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
stop
start
}
reload() {
restart
}
force_reload() {
restart
}
rh_status() {
status $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
restart
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
exit 2
esac
exit $?

View File

@ -0,0 +1,92 @@
%define tinyproxy_confdir %{_sysconfdir}/tinyproxy
%define tinyproxy_datadir %{_datadir}/tinyproxy
Name: tinyproxy
Version: @VERSION@
Release: 2%{?dist}
Summary: A small, efficient HTTP/SSL proxy daemon
Group: System Environment/Daemons
License: GPLv2+
URL: https://www.banu.com/tinyproxy/
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Source0: https://www.banu.com/pub/tinyproxy/1.6/%{name}-%{version}.tar.gz
Source1: %{name}.init
Source2: %{name}.conf
Requires(post): chkconfig
Requires(preun): chkconfig
Requires(preun): initscripts
%description
tinyproxy is a small, efficient HTTP/SSL proxy daemon released under the
GNU General Public License (GPL). tinyproxy is very useful in a small
network setting, where a larger proxy like Squid would either be too
resource intensive, or a security risk.
%prep
%setup -q
%build
%configure --with-config=%{tinyproxy_confdir}/%{name}.conf
make %{?_smp_mflags}
%install
rm -rf %{buildroot}
make install-exec DESTDIR=%{buildroot}
# The default 'make install' installs too many items, so we trim it down
# and install manually
%{__install} -p -D -m 0755 %{SOURCE1} %{buildroot}%{_initrddir}/%{name}
%{__install} -p -D -m 0644 %{SOURCE2} %{buildroot}%{tinyproxy_confdir}/%{name}.conf
%{__install} -d -m 0755 %{buildroot}%{tinyproxy_datadir}
%{__install} -p -D -m 0644 ./doc/%{name}.8 %{buildroot}%{_mandir}/man8/%{name}.8
for htmlfile in $(find ./doc/ -type f -name '*.html')
do
%{__install} -p -m 0644 $htmlfile %{buildroot}%{tinyproxy_datadir}
done
%clean
rm -rf %{buildroot}
%post
/sbin/chkconfig --add %{name}
%preun
if [ $1 = 0 ]; then
/sbin/service %{name} stop >/dev/null 2>&1
/sbin/chkconfig --del %{name}
fi
%postun
if [ "$1" -ge "1" ]; then
/sbin/service %{name} condrestart > /dev/null 2>&1 || :
fi
%files
%defattr(-,root,root,-)
%doc AUTHORS COPYING README doc/*.txt
%{_sbindir}/%{name}
%{_mandir}/man8/%{name}.8.gz
%{_initrddir}/%{name}
%dir %{tinyproxy_datadir}
%dir %{tinyproxy_datadir}/*
%dir %{tinyproxy_confdir}
%config(noreplace) %{tinyproxy_confdir}/%{name}.conf
%changelog
* Wed Apr 16 2008 Jeremy Hinegardner <jeremy at hinegardner dot org> - 1.6.3-2
- fix spec review issues
- fix initscript
* Sun Mar 09 2008 Jeremy Hinegardner <jeremy at hinegardner dot org> - 1.6.3-1
- Initial rpm configuration

View File

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

View File

@ -1,10 +0,0 @@
#!/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}"

View File

@ -1,19 +0,0 @@
#!/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
gitstr=$(git describe --match '[0-9]*.[0-9]*.*' 2>/dev/null)
if test "x$?" != x0 ; then
sed 's/$/-git/' < VERSION
else
printf "%s\n" "$gitstr" | sed -e 's/-g/-git-/'
fi
else
sed 's/$/-git/' < VERSION
fi
else
cat VERSION
fi

4
src/.gitignore vendored
View File

@ -2,6 +2,10 @@
.libs
Makefile
Makefile.in
grammar.c
grammar.h
grammar.output
scanner.c
tinyproxy
*.o
*.pcno

View File

@ -1,71 +1,49 @@
# tinyproxy - A fast light-weight HTTP proxy
# Copyright (C) 2000 Robert James Kaes <rjkaes@users.sourceforge.net>
# $Id: Makefile.am,v 1.17 2003-06-26 18:23:01 rjkaes Exp $
#
# 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.
# Copyright (C) 2000 Robert James Kaes (rjkaes@flarenet.com)
#
# 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.
# 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, 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.
pkgsysconfdir = $(sysconfdir)/$(PACKAGE)
bin_PROGRAMS = tinyproxy
AM_CPPFLAGS = \
-DSYSCONFDIR=\"${pkgsysconfdir}\" \
-DLOCALSTATEDIR=\"${localstatedir}\"
sbin_PROGRAMS = tinyproxy
tinyproxy_SOURCES = \
hostspec.c hostspec.h \
acl.c acl.h \
anonymous.c anonymous.h \
buffer.c buffer.h \
child.c child.h \
common.h \
conf-tokens.c conf-tokens.h \
conf.c conf.h \
conns.c conns.h \
daemon.c daemon.h \
hashmap.c hashmap.h \
heap.c heap.h \
html-error.c html-error.h \
http-message.c http-message.h \
htmlerror.c htmlerror.h \
http_message.c http_message.h \
log.c log.h \
network.c network.h \
reqs.c reqs.h \
sock.c sock.h \
stats.c stats.h \
text.c text.h \
main.c main.h \
tinyproxy.c tinyproxy.h \
utils.c utils.h \
upstream.c upstream.h \
basicauth.c basicauth.h \
base64.c base64.h \
sblist.c sblist.h \
hsearch.c hsearch.h \
orderedmap.c orderedmap.h \
loop.c loop.h \
mypoll.c mypoll.h \
connect-ports.c connect-ports.h
vector.c vector.h \
grammar.y scanner.l \
regexp.h
EXTRA_tinyproxy_SOURCES = filter.c filter.h \
reverse-proxy.c reverse-proxy.h \
transparent-proxy.c transparent-proxy.h
EXTRA_DIST = gnuregex.c gnuregex.h
EXTRA_tinyproxy_SOURCES = filter.c filter.h grammar.h
tinyproxy_DEPENDENCIES = @ADDITIONAL_OBJECTS@
tinyproxy_LDADD = @ADDITIONAL_OBJECTS@ -lpthread
tinyproxy_LDADD = @ADDITIONAL_OBJECTS@
if HAVE_GPERF
conf-tokens.c: conf-tokens-gperf.inc
conf-tokens-gperf.inc: conf-tokens.gperf
$(GPERF) $< > $@
endif
EXTRA_DIST = conf-tokens.gperf conf-tokens-gperf.inc
scanner.c: scanner.l grammar.h
$(LEX) $(LEX_FLAGS) $(LFLAGS) -i $< && mv $(LEX_OUTPUT_ROOT).c $@

425
src/acl.c
View File

@ -1,62 +1,49 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2000, 2002 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: acl.c,v 1.16 2002-06-05 16:59:21 rjkaes Exp $
*
* 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.
*/
/* This system handles Access Control for use of this daemon. A list of
* This system handles Access Control for use of this daemon. A list of
* domains, or IP addresses (including IP blocks) are stored in a list
* which is then used to compare incoming connections.
*
* Copyright (C) 2000,2002 Robert James Kaes (rjkaes@flarenet.com)
*
* 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, 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.
*/
#include "main.h"
#include "tinyproxy.h"
#include "acl.h"
#include "heap.h"
#include "log.h"
#include "network.h"
#include "sock.h"
#include "sblist.h"
#include "hostspec.h"
/*
* Hold the information about a particular access control. We store
* whether it's an ALLOW or DENY entry, and also whether it's a string
* entry (like a domain name) or an IP entry.
*/
struct acl_s {
acl_access_t access;
struct hostspec h;
acl_access_t acl_access;
enum { ACL_STRING, ACL_NUMERIC } type;
char *location;
int netmask;
struct acl_s *next;
};
static struct acl_s *access_list = NULL;
/**
* If the access list has not been set up, create it.
/*
* Take a netmask number (between 0 and 32) and returns a network ordered
* value for comparison.
*/
static int init_access_list(acl_list_t *access_list)
static in_addr_t
make_netmask(int netmask_num)
{
if (!*access_list) {
*access_list = sblist_new(sizeof(struct acl_s), 16);
if (!*access_list) {
log_message (LOG_ERR,
"Unable to allocate memory for access list");
return -1;
}
}
assert(netmask_num >= 0 && netmask_num <= 32);
return 0;
return htonl(~((1 << (32 - netmask_num)) - 1));
}
/*
@ -69,25 +56,80 @@ static int init_access_list(acl_list_t *access_list)
* 0 otherwise.
*/
int
insert_acl (char *location, acl_access_t access_type, acl_list_t *access_list)
insert_acl(char *location, acl_access_t access_type)
{
struct acl_s acl;
size_t i;
struct acl_s **rev_acl_ptr, *acl_ptr, *new_acl_ptr;
char *nptr;
assert (location != NULL);
assert(location != NULL);
if (init_access_list(access_list) != 0)
return -1;
/*
* First check to see if the location is a string or numeric.
*/
for (i = 0; location[i] != '\0'; i++) {
/*
* Numeric strings can not contain letters, so test on it.
*/
if (isalpha((unsigned char) location[i])) {
break;
}
}
/*
* Start populating the access control structure.
*/
memset (&acl, 0, sizeof (struct acl_s));
acl.access = access_type;
if(hostspec_parse(location, &acl.h) || acl.h.type == HST_NONE)
return -1;
/*
* Add a new ACL to the list.
*/
rev_acl_ptr = &access_list;
acl_ptr = access_list;
while (acl_ptr) {
rev_acl_ptr = &acl_ptr->next;
acl_ptr = acl_ptr->next;
}
new_acl_ptr = safemalloc(sizeof(struct acl_s));
if (!new_acl_ptr) {
return -1;
}
if(!sblist_add(*access_list, &acl)) return -1;
return 0;
new_acl_ptr->acl_access = access_type;
if (location[i] == '\0') {
DEBUG2("ACL \"%s\" is a number.", location);
/*
* We did not break early, so this a numeric location.
* Check for a netmask.
*/
new_acl_ptr->type = ACL_NUMERIC;
nptr = strchr(location, '/');
if (nptr) {
*nptr++ = '\0';
new_acl_ptr->netmask = strtol(nptr, NULL, 10);
if (new_acl_ptr->netmask < 0
|| new_acl_ptr->netmask > 32) {
safefree(new_acl_ptr);
return -1;
}
} else {
new_acl_ptr->netmask = 32;
}
} else {
DEBUG2("ACL \"%s\" is a string.", location);
new_acl_ptr->type = ACL_STRING;
new_acl_ptr->netmask = 32;
}
new_acl_ptr->location = safestrdup(location);
if (!new_acl_ptr->location) {
safefree(new_acl_ptr);
return -1;
}
*rev_acl_ptr = new_acl_ptr;
new_acl_ptr->next = acl_ptr;
return 0;
}
/*
@ -99,198 +141,137 @@ insert_acl (char *location, acl_access_t access_type, acl_list_t *access_list)
* 1 if host is allowed
* -1 if no tests match, so skip
*/
static int
acl_string_processing (struct acl_s *acl, const char *ip_address,
union sockaddr_union *addr, char *string_addr)
static inline int
acl_string_processing(struct acl_s* aclptr,
const char* ip_address,
const char* string_address)
{
int match;
struct addrinfo hints, *res, *ressave;
size_t test_length, match_length;
char ipbuf[512];
int i;
struct hostent* result;
size_t test_length, match_length;
assert (acl && acl->h.type == HST_STRING);
assert (ip_address && strlen (ip_address) > 0);
/*
* If the first character of the ACL string is a period, we need to
* do a string based test only; otherwise, we can do a reverse
* lookup test as well.
*/
if (aclptr->location[0] != '.') {
/* It is not a partial domain, so do a reverse lookup. */
result = gethostbyname(aclptr->location);
if (!result)
goto STRING_TEST;
for (i = 0; result->h_addr_list[i]; ++i) {
if (strcmp(ip_address,
inet_ntoa(*((struct in_addr*)result->h_addr_list[i]))) == 0) {
/* We have a match */
if (aclptr->acl_access == ACL_DENY) {
return 0;
} else {
DEBUG2("Matched using reverse domain lookup: %s", ip_address);
return 1;
}
}
}
/*
* If the first character of the ACL string is a period, we need to
* do a string based test only; otherwise, we can do a reverse
* lookup test as well.
*/
if (acl->h.address.string[0] != '.') {
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo (acl->h.address.string, NULL, &hints, &res) != 0)
goto STRING_TEST;
ressave = res;
match = FALSE;
do {
get_ip_string (res->ai_addr, ipbuf, sizeof (ipbuf));
if (strcmp (ip_address, ipbuf) == 0) {
match = TRUE;
break;
}
} while ((res = res->ai_next) != NULL);
freeaddrinfo (ressave);
if (match) {
if (acl->access == ACL_DENY)
return 0;
else
return 1;
}
}
/*
* If we got this far, the reverse didn't match, so drop down
* to a standard string test.
*/
}
STRING_TEST:
if(string_addr[0] == 0) {
/* only do costly hostname resolution when it is absolutely needed,
and only once */
if(getnameinfo ((void *) addr, sizeof (*addr),
string_addr, HOSTNAME_LENGTH, NULL, 0, 0) != 0)
return -1;
}
test_length = strlen(string_address);
match_length = strlen(aclptr->location);
test_length = strlen (string_addr);
match_length = strlen (acl->h.address.string);
/*
* If the string length is shorter than AC string, return a -1 so
* that the "driver" will skip onto the next control in the list.
*/
if (test_length < match_length)
return -1;
/*
* If the string length is shorter than AC string, return a -1 so
* that the "driver" will skip onto the next control in the list.
*/
if (test_length < match_length)
return -1;
if (strcasecmp(string_address + (test_length - match_length), aclptr->location) == 0) {
if (aclptr->acl_access == ACL_DENY)
return 0;
else
return 1;
}
if (strcasecmp
(string_addr + (test_length - match_length),
acl->h.address.string) == 0) {
if (acl->access == ACL_DENY)
return 0;
else
return 1;
}
/* Indicate that no tests succeeded, so skip to next control. */
return -1;
/* Indicate that no tests succeeded, so skip to next control. */
return -1;
}
/*
* Compare the supplied numeric IP address with the supplied ACL structure.
*
* Return:
* 1 IP address is allowed
* 0 IP address is denied
* -1 neither allowed nor denied.
*/
static int check_numeric_acl (const struct acl_s *acl, uint8_t addr[IPV6_LEN])
{
uint8_t x, y;
int i;
assert (acl && acl->h.type == HST_NUMERIC);
for (i = 0; i != IPV6_LEN; ++i) {
x = addr[i] & acl->h.address.ip.mask[i];
y = acl->h.address.ip.network[i];
/* If x and y don't match, the IP addresses don't match */
if (x != y)
return -1;
}
/* The addresses match, return the permission */
return (acl->access == ACL_ALLOW);
}
/*
* Checks whether a connection is allowed.
* Checks whether file descriptor is allowed.
*
* Returns:
* 1 if allowed
* 0 if denied
*/
int check_acl (const char *ip, union sockaddr_union *addr, acl_list_t access_list)
int
check_acl(int fd, const char* ip_address, const char* string_address)
{
struct acl_s *acl;
int perm = 0, is_numeric_addr;
size_t i;
char string_addr[HOSTNAME_LENGTH];
uint8_t numeric_addr[IPV6_LEN];
struct acl_s* aclptr;
int ret;
assert (ip != NULL);
assert (addr != NULL);
assert(fd >= 0);
assert(ip_address != NULL);
assert(string_address != NULL);
string_addr[0] = 0;
/*
* If there is no access list allow everything.
*/
aclptr = access_list;
if (!aclptr)
return 1;
/*
* If there is no access list allow everything.
*/
if (!access_list)
return 1;
while (aclptr) {
if (aclptr->type == ACL_STRING) {
ret = acl_string_processing(aclptr,
ip_address,
string_address);
if (ret == 0)
goto UNAUTHORIZED;
else if (ret == 1)
return 1;
is_numeric_addr = (full_inet_pton (ip, &numeric_addr) > 0);
aclptr = aclptr->next;
continue;
} else {
struct in_addr test_addr, match_addr;
in_addr_t netmask_addr;
for (i = 0; i < sblist_getsize (access_list); ++i) {
acl = sblist_get (access_list, i);
switch (acl->h.type) {
case HST_STRING:
perm = acl_string_processing (acl, ip, addr, string_addr);
break;
if (ip_address[0] == 0) {
aclptr = aclptr->next;
continue;
}
case HST_NUMERIC:
if (ip[0] == '\0')
continue;
inet_aton(ip_address, &test_addr);
inet_aton(aclptr->location, &match_addr);
perm = is_numeric_addr
? check_numeric_acl (acl, numeric_addr)
: -1;
break;
netmask_addr = make_netmask(aclptr->netmask);
case HST_NONE:
perm = -1;
break;
}
if ((test_addr.s_addr & netmask_addr) ==
(match_addr.s_addr & netmask_addr)) {
if (aclptr->acl_access == ACL_DENY)
goto UNAUTHORIZED;
else
return 1;
}
}
/*
* Check the return value too see if the IP address is
* allowed or denied.
*/
if (perm == 0)
break;
else if (perm == 1)
return perm;
}
/*
* Dropped through... go on to the next one.
*/
aclptr = aclptr->next;
}
/*
* Deny all connections by default.
*/
log_message (LOG_NOTICE, "Unauthorized connection from \"%s\".",
ip);
return 0;
}
void flush_access_list (acl_list_t access_list)
{
struct acl_s *acl;
size_t i;
if (!access_list) {
return;
}
/*
* We need to free allocated data hanging off the acl entries
* before we can free the acl entries themselves.
* A hierarchical memory system would be great...
*/
for (i = 0; i < sblist_getsize (access_list); ++i) {
acl = sblist_get (access_list, i);
if (acl->h.type == HST_STRING) {
safefree (acl->h.address.string);
}
}
sblist_free (access_list);
/*
* Deny all connections by default.
*/
UNAUTHORIZED:
log_message(LOG_NOTICE, "Unauthorized connection from \"%s\" [%s].",
string_address, ip_address);
return 0;
}

View File

@ -1,36 +1,26 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2000 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: acl.h,v 1.3 2002-04-17 20:52:45 rjkaes Exp $
*
* 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.
* See 'acl.c' for detailed information.
*
* 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.
* Copyright (C) 2000 Robert James Kaes (rjkaes@flarenet.com)
*
* 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.
* 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, 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.
*/
/* See 'acl.c' for detailed information. */
#ifndef TINYPROXY_ACL_H
#define TINYPROXY_ACL_H
#include "sblist.h"
#include "sock.h"
typedef enum { ACL_ALLOW, ACL_DENY } acl_access_t;
typedef sblist* acl_list_t;
extern int insert_acl (char *location, acl_access_t access_type,
acl_list_t *access_list);
extern int check_acl (const char *ip_address, union sockaddr_union *addr,
acl_list_t access_list);
extern void flush_access_list (acl_list_t access_list);
extern int insert_acl(char *location, acl_access_t access_type);
extern int check_acl(int fd, const char* ip_address, const char* string_address);
#endif

View File

@ -1,48 +1,47 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2000 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: anonymous.c,v 1.14 2002-05-23 18:20:27 rjkaes Exp $
*
* 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.
* Handles insertion and searches for headers which should be let through when
* the anonymous feature is turned on.
*
* 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.
* Copyright (C) 2000 Robert James Kaes (rjkaes@flarenet.com)
*
* 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.
* 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, 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.
*/
/* Handles insertion and searches for headers which should be let through
* when the anonymous feature is turned on.
*/
#include "main.h"
#include "tinyproxy.h"
#include "anonymous.h"
#include "hsearch.h"
#include "hashmap.h"
#include "heap.h"
#include "log.h"
#include "conf.h"
short int is_anonymous_enabled (struct config_s *conf)
static hashmap_t anonymous_map = NULL;
short int
is_anonymous_enabled(void)
{
return (conf->anonymous_map != NULL) ? 1 : 0;
return (anonymous_map != NULL) ? 1 : 0;
}
/*
* Search for the header. This function returns a positive value greater than
* zero if the string was found, zero if it wasn't and negative upon error.
*/
int anonymous_search (struct config_s *conf, const char *s)
int
anonymous_search(char *s)
{
assert (s != NULL);
assert (conf->anonymous_map != NULL);
assert(s != NULL);
assert(anonymous_map != NULL);
return !!htab_find (conf->anonymous_map, s);
return hashmap_search(anonymous_map, s);
}
/*
@ -51,21 +50,24 @@ int anonymous_search (struct config_s *conf, const char *s)
* Return -1 if there is an error, otherwise a 0 is returned if the insert was
* successful.
*/
int anonymous_insert (struct config_s *conf, char *s)
int
anonymous_insert(char *s)
{
assert (s != NULL);
char data = 1;
if (!conf->anonymous_map) {
conf->anonymous_map = htab_create (32);
if (!conf->anonymous_map)
return -1;
}
assert(s != NULL);
if (htab_find (conf->anonymous_map, s)) {
/* The key was already found. */
return 0;
}
if (!anonymous_map) {
anonymous_map = hashmap_create(32);
if (!anonymous_map)
return -1;
}
/* Insert the new key */
return htab_insert (conf->anonymous_map, s, HTV_N(1)) ? 0 : -1;
if (hashmap_search(anonymous_map, s) > 0) {
/* The key was already found, so return a positive number. */
return 0;
}
/* Insert the new key */
return hashmap_insert(anonymous_map, s, &data, sizeof(data));
}

View File

@ -1,28 +1,25 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2000 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: anonymous.h,v 1.6 2001-12-15 20:08:24 rjkaes Exp $
*
* 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.
* See 'anonymous.c' for a detailed description.
*
* 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.
* Copyright (C) 2000 Robert James Kaes (rjkaes@flarenet.com)
*
* 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.
* 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, 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.
*/
/* See 'anonymous.c' for detailed information. */
#ifndef _TINYPROXY_ANONYMOUS_H_
#define _TINYPROXY_ANONYMOUS_H_
extern short int is_anonymous_enabled (struct config_s *conf);
extern int anonymous_search (struct config_s *conf, const char *s);
extern int anonymous_insert (struct config_s *conf, char *s);
extern short int is_anonymous_enabled(void);
extern int anonymous_search(char *s);
extern int anonymous_insert(char *s);
#endif

View File

@ -1,57 +0,0 @@
/* 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,29 +0,0 @@
/* 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.
*/
#ifndef TINYPROXY_BASE64_H
#define TINYPROXY_BASE64_H
#include <stddef.h>
/* calculates number of bytes base64-encoded stream of N bytes will take. */
#define BASE64ENC_BYTES(N) (((N+2)/3)*4)
void base64enc(char *dst, const void* src, size_t count);
#endif

View File

@ -1,97 +0,0 @@
/* 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 (sblist *authlist,
const char *user, const char *pass)
{
char b[BASE64ENC_BYTES((256+2)-1) + 1], *s;
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 (!(s = safestrdup(b)) || !sblist_add(authlist, &s)) {
safefree(s);
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 (sblist *authlist, const char *authstring)
{
size_t i;
char** entry;
if (!authlist) return 0;
for (i = 0; i < sblist_getsize(authlist); i++) {
entry = sblist_get (authlist, i);
if (entry && strcmp (authstring, *entry) == 0)
return 1;
}
return 0;
}

View File

@ -1,35 +0,0 @@
/* 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 "sblist.h"
extern ssize_t basicauth_string(const char *user, const char *pass,
char *buf, size_t bufsize);
extern void basicauth_add (sblist *authlist,
const char *user, const char *pass);
extern int basicauth_check (sblist *authlist, const char *authstring);
#endif

View File

@ -1,31 +1,27 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 1999, 2001 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: buffer.c,v 1.22 2002-05-24 04:45:32 rjkaes Exp $
*
* 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.
*/
/* The buffer used in each connection is a linked list of lines. As the lines
* The buffer used in each connection is a linked list of lines. As the lines
* are read in and written out the buffer expands and contracts. Basically,
* by using this method we can increase the buffer size dynamically. However,
* we have a hard limit of 64 KB for the size of the buffer. The buffer can be
* thought of as a queue were we act on both the head and tail. The various
* functions act on each end (the names are taken from what Perl uses to act on
* the ends of an array. :)
*
* Copyright (C) 1999,2001 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, 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.
*/
#include "main.h"
#include "tinyproxy.h"
#include "buffer.h"
#include "heap.h"
@ -35,10 +31,10 @@
#define BUFFER_TAIL(x) (x)->tail
struct bufline_s {
unsigned char *string; /* the actual string of data */
struct bufline_s *next; /* pointer to next in linked list */
size_t length; /* length of the string of data */
size_t pos; /* start sending from this offset */
unsigned char *string; /* the actual string of data */
struct bufline_s *next; /* pointer to next in linked list */
size_t length; /* length of the string of data */
size_t pos; /* start sending from this offset */
};
/*
@ -46,9 +42,9 @@ struct bufline_s {
* (and includes the total size)
*/
struct buffer_s {
struct bufline_s *head; /* top of the buffer */
struct bufline_s *tail; /* bottom of the buffer */
size_t size; /* total size of the buffer */
struct bufline_s *head; /* top of the buffer */
struct bufline_s *tail; /* bottom of the buffer */
size_t size; /* total size of the buffer */
};
/*
@ -56,152 +52,155 @@ struct buffer_s {
* to the buffer. The data IS copied, so make sure if you allocated your
* data buffer on the heap, delete it because you now have TWO copies.
*/
static struct bufline_s *makenewline (unsigned char *data, size_t length)
static struct bufline_s *
makenewline(unsigned char *data, size_t length)
{
struct bufline_s *newline;
struct bufline_s *newline;
assert (data != NULL);
assert (length > 0);
assert(data != NULL);
assert(length > 0);
newline = (struct bufline_s *) safemalloc (sizeof (struct bufline_s));
if (!newline)
return NULL;
if (!(newline = safemalloc(sizeof(struct bufline_s))))
return NULL;
newline->string = (unsigned char *) safemalloc (length);
if (!newline->string) {
safefree (newline);
return NULL;
}
if (!(newline->string = safemalloc(length))) {
safefree(newline);
return NULL;
}
memcpy (newline->string, data, length);
memcpy(newline->string, data, length);
newline->next = NULL;
newline->length = length;
newline->next = NULL;
newline->length = length;
/* Position our "read" pointer at the beginning of the data */
newline->pos = 0;
/* Position our "read" pointer at the beginning of the data */
newline->pos = 0;
return newline;
return newline;
}
/*
* Free the allocated buffer line
*/
static void free_line (struct bufline_s *line)
static void
free_line(struct bufline_s *line)
{
assert (line != NULL);
assert(line != NULL);
if (!line)
return;
if (!line)
return;
if (line->string)
safefree (line->string);
if (line->string)
safefree(line->string);
safefree (line);
safefree(line);
}
/*
* Create a new buffer
*/
struct buffer_s *new_buffer (void)
struct buffer_s *
new_buffer(void)
{
struct buffer_s *buffptr;
struct buffer_s *buffptr;
buffptr = (struct buffer_s *) safemalloc (sizeof (struct buffer_s));
if (!buffptr)
return NULL;
if (!(buffptr = safemalloc(sizeof(struct buffer_s))))
return NULL;
/*
* Since the buffer is initially empty, set the HEAD and TAIL
* pointers to NULL since they can't possibly point anywhere at the
* moment.
*/
BUFFER_HEAD (buffptr) = BUFFER_TAIL (buffptr) = NULL;
buffptr->size = 0;
/*
* Since the buffer is initially empty, set the HEAD and TAIL
* pointers to NULL since they can't possibly point anywhere at the
* moment.
*/
BUFFER_HEAD(buffptr) = BUFFER_TAIL(buffptr) = NULL;
buffptr->size = 0;
return buffptr;
return buffptr;
}
/*
* Delete all the lines in the buffer and the buffer itself
*/
void delete_buffer (struct buffer_s *buffptr)
void
delete_buffer(struct buffer_s *buffptr)
{
struct bufline_s *next;
struct bufline_s *next;
assert (buffptr != NULL);
assert(buffptr != NULL);
while (BUFFER_HEAD (buffptr)) {
next = BUFFER_HEAD (buffptr)->next;
free_line (BUFFER_HEAD (buffptr));
BUFFER_HEAD (buffptr) = next;
}
while (BUFFER_HEAD(buffptr)) {
next = BUFFER_HEAD(buffptr)->next;
free_line(BUFFER_HEAD(buffptr));
BUFFER_HEAD(buffptr) = next;
}
safefree (buffptr);
safefree(buffptr);
}
/*
* Return the current size of the buffer.
*/
size_t buffer_size (struct buffer_s *buffptr)
size_t buffer_size(struct buffer_s *buffptr)
{
return buffptr->size;
return buffptr->size;
}
/*
* Push a new line on to the end of the buffer.
*/
int add_to_buffer (struct buffer_s *buffptr, unsigned char *data, size_t length)
int
add_to_buffer(struct buffer_s *buffptr, unsigned char *data, size_t length)
{
struct bufline_s *newline;
struct bufline_s *newline;
assert (buffptr != NULL);
assert (data != NULL);
assert (length > 0);
assert(buffptr != NULL);
assert(data != NULL);
assert(length > 0);
/*
* Sanity check here. A buffer with a non-NULL head pointer must
* have a size greater than zero, and vice-versa.
*/
if (BUFFER_HEAD (buffptr) == NULL)
assert (buffptr->size == 0);
else
assert (buffptr->size > 0);
/*
* Sanity check here. A buffer with a non-NULL head pointer must
* have a size greater than zero, and vice-versa.
*/
if (BUFFER_HEAD(buffptr) == NULL)
assert(buffptr->size == 0);
else
assert(buffptr->size > 0);
/*
* Make a new line so we can add it to the buffer.
*/
if (!(newline = makenewline (data, length)))
return -1;
/*
* Make a new line so we can add it to the buffer.
*/
if (!(newline = makenewline(data, length)))
return -1;
if (buffptr->size == 0)
BUFFER_HEAD (buffptr) = BUFFER_TAIL (buffptr) = newline;
else {
BUFFER_TAIL (buffptr)->next = newline;
BUFFER_TAIL (buffptr) = newline;
}
if (buffptr->size == 0)
BUFFER_HEAD(buffptr) = BUFFER_TAIL(buffptr) = newline;
else {
BUFFER_TAIL(buffptr)->next = newline;
BUFFER_TAIL(buffptr) = newline;
}
buffptr->size += length;
buffptr->size += length;
return 0;
return 0;
}
/*
* Remove the first line from the top of the buffer
*/
static struct bufline_s *remove_from_buffer (struct buffer_s *buffptr)
static struct bufline_s *
remove_from_buffer(struct buffer_s *buffptr)
{
struct bufline_s *line;
struct bufline_s *line;
assert (buffptr != NULL);
assert (BUFFER_HEAD (buffptr) != NULL);
assert(buffptr != NULL);
assert(BUFFER_HEAD(buffptr) != NULL);
line = BUFFER_HEAD (buffptr);
BUFFER_HEAD (buffptr) = line->next;
line = BUFFER_HEAD(buffptr);
BUFFER_HEAD(buffptr) = line->next;
buffptr->size -= line->length;
buffptr->size -= line->length;
return line;
return line;
}
/*
@ -209,113 +208,115 @@ static struct bufline_s *remove_from_buffer (struct buffer_s *buffptr)
* Takes a connection and returns the number of bytes read.
*/
#define READ_BUFFER_SIZE (1024 * 2)
ssize_t read_buffer (int fd, struct buffer_s * buffptr)
ssize_t
read_buffer(int fd, struct buffer_s * buffptr)
{
ssize_t bytesin;
unsigned char *buffer;
ssize_t bytesin;
unsigned char *buffer;
assert (fd >= 0);
assert (buffptr != NULL);
assert(fd >= 0);
assert(buffptr != NULL);
/*
* Don't allow the buffer to grow larger than MAXBUFFSIZE
*/
if (buffptr->size >= MAXBUFFSIZE)
return 0;
/*
* Don't allow the buffer to grow larger than MAXBUFFSIZE
*/
if (buffptr->size >= MAXBUFFSIZE)
return 0;
buffer = (unsigned char *) safemalloc (READ_BUFFER_SIZE);
if (!buffer) {
return -ENOMEM;
}
buffer = safemalloc(READ_BUFFER_SIZE);
if (!buffer) {
return -ENOMEM;
}
bytesin = read (fd, buffer, READ_BUFFER_SIZE);
bytesin = read(fd, buffer, READ_BUFFER_SIZE);
if (bytesin > 0) {
if (add_to_buffer (buffptr, buffer, bytesin) < 0) {
log_message (LOG_ERR,
"readbuff: add_to_buffer() error.");
bytesin = -1;
}
} else if (bytesin == 0) {
/* connection was closed by client */
bytesin = -1;
} else {
switch (errno) {
if (bytesin > 0) {
if (add_to_buffer(buffptr, buffer, bytesin) < 0) {
log_message(LOG_ERR,
"readbuff: add_to_buffer() error.");
bytesin = -1;
}
} else {
if (bytesin == 0) {
/* connection was closed by client */
bytesin = -1;
} else {
switch (errno) {
#ifdef EWOULDBLOCK
case EWOULDBLOCK:
case EWOULDBLOCK:
#else
# ifdef EAGAIN
case EAGAIN:
case EAGAIN:
# endif
#endif
case EINTR:
bytesin = 0;
break;
default:
log_message (LOG_ERR,
"read_buffer: read() failed on fd %d: %s",
fd, strerror(errno));
bytesin = -1;
break;
}
}
case EINTR:
bytesin = 0;
break;
default:
log_message(LOG_ERR,
"readbuff: recv() error \"%s\" on file descriptor %d",
strerror(errno), fd);
bytesin = -1;
break;
}
}
}
safefree (buffer);
return bytesin;
safefree(buffer);
return bytesin;
}
/*
* Write the bytes in the buffer to the socket.
* Takes a connection and returns the number of bytes written.
*/
ssize_t write_buffer (int fd, struct buffer_s * buffptr)
ssize_t
write_buffer(int fd, struct buffer_s * buffptr)
{
ssize_t bytessent;
struct bufline_s *line;
ssize_t bytessent;
struct bufline_s *line;
assert (fd >= 0);
assert (buffptr != NULL);
assert(fd >= 0);
assert(buffptr != NULL);
if (buffptr->size == 0)
return 0;
if (buffptr->size == 0)
return 0;
/* Sanity check. It would be bad to be using a NULL pointer! */
assert (BUFFER_HEAD (buffptr) != NULL);
line = BUFFER_HEAD (buffptr);
/* Sanity check. It would be bad to be using a NULL pointer! */
assert(BUFFER_HEAD(buffptr) != NULL);
line = BUFFER_HEAD(buffptr);
bytessent =
send (fd, line->string + line->pos, line->length - line->pos,
MSG_NOSIGNAL);
bytessent =
send(fd, line->string + line->pos, line->length - line->pos, MSG_NOSIGNAL);
if (bytessent >= 0) {
/* bytes sent, adjust buffer */
line->pos += bytessent;
if (line->pos == line->length)
free_line (remove_from_buffer (buffptr));
return bytessent;
} else {
switch (errno) {
if (bytessent >= 0) {
/* bytes sent, adjust buffer */
line->pos += bytessent;
if (line->pos == line->length)
free_line(remove_from_buffer(buffptr));
return bytessent;
} else {
switch (errno) {
#ifdef EWOULDBLOCK
case EWOULDBLOCK:
case EWOULDBLOCK:
#else
# ifdef EAGAIN
case EAGAIN:
case EAGAIN:
# endif
#endif
case EINTR:
return 0;
case ENOBUFS:
case ENOMEM:
log_message (LOG_ERR,
"writebuff: write() error [NOBUFS/NOMEM] \"%s\" on "
"file descriptor %d", strerror (errno),
fd);
return 0;
default:
log_message (LOG_ERR,
"writebuff: write() error \"%s\" on file descriptor %d",
strerror (errno), fd);
return -1;
}
}
case EINTR:
return 0;
case ENOBUFS:
case ENOMEM:
log_message(LOG_ERR,
"writebuff: write() error [NOBUFS/NOMEM] \"%s\" on file descriptor %d",
strerror(errno), fd);
return 0;
default:
log_message(LOG_ERR,
"writebuff: write() error \"%s\" on file descriptor %d",
strerror(errno), fd);
return -1;
}
}
}

View File

@ -1,40 +1,37 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 1999 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: buffer.h,v 1.8 2002-05-14 00:43:38 rjkaes Exp $
*
* 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.
* See 'buffer.c' for a detailed description.
*
* 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.
* Copyright (C) 1999 Robert James Kaes (rjkaes@flarenet.com)
*
* 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.
* 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, 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.
*/
/* See 'buffer.c' for detailed information. */
#ifndef _TINYPROXY_BUFFER_H_
#define _TINYPROXY_BUFFER_H_
/* Forward declaration */
struct buffer_s;
extern struct buffer_s *new_buffer (void);
extern void delete_buffer (struct buffer_s *buffptr);
extern size_t buffer_size (struct buffer_s *buffptr);
extern struct buffer_s *new_buffer(void);
extern void delete_buffer(struct buffer_s *buffptr);
extern size_t buffer_size(struct buffer_s *buffptr);
/*
* Add a new line to the given buffer. The data IS copied into the structure.
*/
extern int add_to_buffer (struct buffer_s *buffptr, unsigned char *data,
size_t length);
extern int add_to_buffer(struct buffer_s *buffptr, unsigned char *data,
size_t length);
extern ssize_t read_buffer (int fd, struct buffer_s *buffptr);
extern ssize_t write_buffer (int fd, struct buffer_s *buffptr);
extern ssize_t read_buffer(int fd, struct buffer_s *buffptr);
extern ssize_t write_buffer(int fd, struct buffer_s *buffptr);
#endif /* __BUFFER_H_ */
#endif /* __BUFFER_H_ */

View File

@ -1,26 +1,22 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2000 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: child.c,v 1.11.2.2 2004-06-14 20:08:12 rjkaes Exp $
*
* 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.
*/
/* Handles the creation/destruction of the various children required for
* Handles the creation/destruction of the various children required for
* processing incoming connections.
*
* Copyright (C) 2000 Robert James Kaes (rjkaes@flarenet.com)
*
* 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, 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.
*/
#include "main.h"
#include "tinyproxy.h"
#include "child.h"
#include "daemon.h"
@ -30,287 +26,418 @@
#include "reqs.h"
#include "sock.h"
#include "utils.h"
#include "conf.h"
#include "sblist.h"
#include "loop.h"
#include "conns.h"
#include "mypoll.h"
#include <pthread.h>
static sblist* listen_fds;
static int listenfd;
static socklen_t addrlen;
struct client {
union sockaddr_union addr;
/*
* Stores the internal data needed for each child (connection)
*/
struct child_s {
pid_t tid;
unsigned int connects;
enum { T_EMPTY, T_WAITING, T_CONNECTED } status;
};
struct child {
pthread_t thread;
struct client client;
struct conn_s conn;
volatile int done;
};
/*
* A pointer to an array of children. A certain number of children are
* created when the program is started.
*/
static struct child_s *child_ptr;
static void* child_thread(void* data)
static struct child_config_s {
int maxclients, maxrequestsperchild;
int maxspareservers, minspareservers, startservers;
} child_config;
static int* servers_waiting; /* servers waiting for a connection */
/*
* Lock/Unlock the "servers_waiting" variable so that two children cannot
* modify it at the same time.
*/
#define SERVER_COUNT_LOCK() _child_lock_wait()
#define SERVER_COUNT_UNLOCK() _child_lock_release()
/* START OF LOCKING SECTION */
/*
* These variables are required for the locking mechanism. Also included
* are the "private" functions for locking/unlocking.
*/
static struct flock lock_it, unlock_it;
static int lock_fd = -1;
static void
_child_lock_init(void)
{
struct child *c = data;
handle_connection (&c->conn, &c->client.addr);
c->done = 1;
return NULL;
char lock_file[] = "/tmp/tinyproxy.servers.lock.XXXXXX";
/* Only allow u+rw bits. This may be required for some versions
* of glibc so that mkstemp() doesn't make us vulnerable.
*/
umask(0177);
lock_fd = mkstemp(lock_file);
unlink(lock_file);
lock_it.l_type = F_WRLCK;
lock_it.l_whence = SEEK_SET;
lock_it.l_start = 0;
lock_it.l_len = 0;
unlock_it.l_type = F_UNLCK;
unlock_it.l_whence = SEEK_SET;
unlock_it.l_start = 0;
unlock_it.l_len = 0;
}
static sblist *childs;
static void collect_threads(void)
static void
_child_lock_wait(void)
{
size_t i;
for (i = 0; i < sblist_getsize(childs); ) {
struct child *c = *((struct child**)sblist_get(childs, i));
if (c->done) {
pthread_join(c->thread, 0);
sblist_delete(childs, i);
safefree(c);
} else i++;
int rc;
while ((rc = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0) {
if (errno == EINTR)
continue;
else
return;
}
}
/*
* This is the main loop accepting new connections.
*/
void child_main_loop (void)
static void
_child_lock_release(void)
{
int connfd;
union sockaddr_union cliaddr_storage;
struct sockaddr *cliaddr = (void*) &cliaddr_storage;
socklen_t clilen;
int nfds = sblist_getsize(listen_fds);
pollfd_struct *fds = safecalloc(nfds, sizeof *fds);
ssize_t i;
int ret, listenfd, was_full = 0;
pthread_attr_t *attrp, attr;
struct child *child;
if (fcntl(lock_fd, F_SETLKW, &unlock_it) < 0)
return;
}
childs = sblist_new(sizeof (struct child*), config->maxclients);
/* END OF LOCKING SECTION */
for (i = 0; i < nfds; i++) {
int *fd = sblist_get(listen_fds, i);
fds[i].fd = *fd;
fds[i].events |= MYPOLL_READ;
}
#define SERVER_INC() do { \
SERVER_COUNT_LOCK(); \
++(*servers_waiting); \
DEBUG2("INC: servers_waiting: %d", *servers_waiting); \
SERVER_COUNT_UNLOCK(); \
} while (0)
/*
* We have to wait for connections on multiple fds,
* so use select/poll/whatever.
*/
while (!config->quit) {
#define SERVER_DEC() do { \
SERVER_COUNT_LOCK(); \
--(*servers_waiting); \
DEBUG2("DEC: servers_waiting: %d", *servers_waiting); \
SERVER_COUNT_UNLOCK(); \
} while (0)
collect_threads();
/*
* Set the configuration values for the various child related settings.
*/
short int
child_configure(child_config_t type, int val)
{
switch (type) {
case CHILD_MAXCLIENTS:
child_config.maxclients = val;
break;
case CHILD_MAXSPARESERVERS:
child_config.maxspareservers = val;
break;
case CHILD_MINSPARESERVERS:
child_config.minspareservers = val;
break;
case CHILD_STARTSERVERS:
child_config.startservers = val;
break;
case CHILD_MAXREQUESTSPERCHILD:
child_config.maxrequestsperchild = val;
break;
default:
DEBUG2("Invalid type (%d)", type);
return -1;
}
if (sblist_getsize(childs) >= config->maxclients) {
if (!was_full)
log_message (LOG_WARNING,
"Maximum number of connections reached. "
"Refusing new connections.");
was_full = 1;
usleep(16);
continue;
}
return 0;
}
was_full = 0;
listenfd = -1;
/*
* This is the main (per child) loop.
*/
static void
child_main(struct child_s* ptr)
{
int connfd;
struct sockaddr *cliaddr;
socklen_t clilen;
/* Handle log rotation if it was requested */
if (received_sighup) {
cliaddr = safemalloc(addrlen);
if (!cliaddr) {
log_message(LOG_CRIT,
"Could not allocate memory for child address.");
exit(0);
}
reload_config (1);
ptr->connects = 0;
while (!config.quit) {
ptr->status = T_WAITING;
clilen = addrlen;
connfd = accept(listenfd, cliaddr, &clilen);
#ifndef NDEBUG
/*
* Enable the TINYPROXY_DEBUG environment variable if you
* want to use the GDB debugger.
*/
if (getenv("TINYPROXY_DEBUG")) {
/* Pause for 10 seconds to allow us to connect debugger */
fprintf(stderr,
"Process has accepted connection: %u\n", ptr->tid);
sleep(10);
fprintf(stderr, "Continuing process: %u\n", ptr->tid);
}
#endif
/*
* Make sure no error occurred...
*/
if (connfd < 0) {
log_message(LOG_ERR, "Accept returned an error (%s) ... retrying.", strerror(errno));
continue;
}
ptr->status = T_CONNECTED;
SERVER_DEC();
handle_connection(connfd);
if (child_config.maxrequestsperchild != 0) {
ptr->connects++;
DEBUG2("%u connections so far...", ptr->connects);
if (ptr->connects == child_config.maxrequestsperchild) {
log_message(LOG_NOTICE,
"Child has reached MaxRequestsPerChild (%u). Killing child.",
ptr->connects);
break;
}
}
SERVER_COUNT_LOCK();
if (*servers_waiting > child_config.maxspareservers) {
/*
* There are too many spare children, kill ourself
* off.
*/
log_message(LOG_NOTICE,
"Waiting servers (%d) exceeds MaxSpareServers (%d). Killing child.",
*servers_waiting, child_config.maxspareservers);
SERVER_COUNT_UNLOCK();
break;
} else {
SERVER_COUNT_UNLOCK();
}
SERVER_INC();
}
ptr->status = T_EMPTY;
safefree(cliaddr);
exit(0);
}
/*
* Fork a child "child" (or in our case a process) and then start up the
* child_main() function.
*/
static int
child_make(struct child_s* ptr)
{
pid_t pid;
if ((pid = fork()) > 0)
return pid; /* parent */
/*
* Reset the SIGNALS so that the child can be reaped.
*/
set_signal_handler(SIGCHLD, SIG_DFL);
set_signal_handler(SIGTERM, SIG_DFL);
set_signal_handler(SIGHUP, SIG_DFL);
child_main(ptr); /* never returns */
return -1;
}
/*
* Create a pool of children to handle incoming connections
*/
short int
child_pool_create(void)
{
unsigned int i;
/*
* Make sure the number of MaxClients is not zero, since this
* variable determines the size of the array created for children
* later on.
*/
if (child_config.maxclients == 0) {
log_message(LOG_ERR,
"child_pool_create: \"MaxClients\" must be greater than zero.");
return -1;
}
if (child_config.startservers == 0) {
log_message(LOG_ERR,
"child_pool_create: \"StartServers\" must be greater than zero.");
return -1;
}
child_ptr = calloc_shared_memory(child_config.maxclients,
sizeof(struct child_s));
if (!child_ptr) {
log_message(LOG_ERR, "Could not allocate memory for children.");
return -1;
}
servers_waiting = malloc_shared_memory(sizeof(int));
if (servers_waiting == MAP_FAILED) {
log_message(LOG_ERR, "Could not allocate memory for child counting.");
return -1;
}
*servers_waiting = 0;
/*
* Create a "locking" file for use around the servers_waiting
* variable.
*/
_child_lock_init();
if (child_config.startservers > child_config.maxclients) {
log_message(LOG_WARNING,
"Can not start more than \"MaxClients\" servers. Starting %u servers instead.",
child_config.maxclients);
child_config.startservers = child_config.maxclients;
}
for (i = 0; i != child_config.maxclients; i++) {
child_ptr[i].status = T_EMPTY;
child_ptr[i].connects = 0;
}
for (i = 0; i != child_config.startservers; i++) {
DEBUG2("Trying to create child %d of %d", i + 1, child_config.startservers);
child_ptr[i].status = T_WAITING;
child_ptr[i].tid = child_make(&child_ptr[i]);
if (child_ptr[i].tid < 0) {
log_message(LOG_WARNING,
"Could not create child number %d of %d",
i, child_config.startservers);
return -1;
} else {
log_message(LOG_INFO,
"Creating child number %d of %d ...",
i + 1, child_config.startservers);
SERVER_INC();
}
}
log_message(LOG_INFO, "Finished creating all children.");
return 0;
}
/*
* Keep the proper number of servers running. This is the birth of the
* servers. It monitors this at least once a second.
*/
void
child_main_loop(void)
{
int i;
while (1) {
if (config.quit)
return;
/* If there are not enough spare servers, create more */
SERVER_COUNT_LOCK();
if (*servers_waiting < child_config.minspareservers) {
log_message(LOG_NOTICE,
"Waiting servers (%d) is less than MinSpareServers (%d). Creating new child.",
*servers_waiting, child_config.minspareservers);
SERVER_COUNT_UNLOCK();
for (i = 0; i != child_config.maxclients; i++) {
if (child_ptr[i].status == T_EMPTY) {
child_ptr[i].status = T_WAITING;
child_ptr[i].tid = child_make(&child_ptr[i]);
if (child_ptr[i].tid < 0) {
log_message(LOG_NOTICE,
"Could not create child");
child_ptr[i].status = T_EMPTY;
break;
}
SERVER_INC();
break;
}
}
} else {
SERVER_COUNT_UNLOCK();
}
sleep(5);
/* Handle log rotation if it was requested */
if (received_sighup) {
truncate_log_file();
#ifdef FILTER_ENABLE
filter_reload ();
#endif /* FILTER_ENABLE */
if (config.filter) {
filter_destroy();
filter_init();
}
log_message(LOG_NOTICE, "Re-reading filter file.");
#endif /* FILTER_ENABLE */
received_sighup = FALSE;
}
ret = mypoll(fds, nfds, -1);
if (ret == -1) {
if (errno == EINTR) {
continue;
}
log_message (LOG_ERR, "error calling " SELECT_OR_POLL ": %s",
strerror(errno));
continue;
} else if (ret == 0) {
log_message (LOG_WARNING, "Strange: " SELECT_OR_POLL " returned 0 "
"but we did not specify a timeout...");
continue;
}
for (i = 0; i < nfds; i++) {
if (fds[i].revents & MYPOLL_READ) {
/*
* only accept the connection on the first
* fd that we find readable. - fair?
*/
listenfd = fds[i].fd;
break;
}
}
if (listenfd == -1) {
log_message(LOG_WARNING, "Strange: None of our listen "
"fds was readable after " SELECT_OR_POLL);
continue;
}
/*
* We have a socket that is readable.
* Continue handling this connection.
*/
clilen = sizeof(cliaddr_storage);
connfd = accept (listenfd, cliaddr, &clilen);
/*
* Make sure no error occurred...
*/
if (connfd < 0) {
log_message (LOG_ERR,
"Accept returned an error (%s) ... retrying.",
strerror (errno));
continue;
}
child = safecalloc(1, sizeof(struct child));
if (!child) {
oom:
close(connfd);
log_message (LOG_CRIT,
"Could not allocate memory for child.");
usleep(16); /* prevent 100% CPU usage in OOM situation */
continue;
}
child->done = 0;
if (!sblist_add(childs, &child)) {
free(child);
goto oom;
}
conn_struct_init(&child->conn);
child->conn.client_fd = connfd;
memcpy(&child->client.addr, &cliaddr_storage, sizeof(cliaddr_storage));
attrp = 0;
if (pthread_attr_init(&attr) == 0) {
attrp = &attr;
pthread_attr_setstacksize(attrp, 256*1024);
}
if (pthread_create(&child->thread, attrp, child_thread, child) != 0) {
sblist_delete(childs, sblist_getsize(childs) -1);
free(child);
goto oom;
received_sighup = FALSE;
}
}
safefree(fds);
}
}
/*
* Go through all the non-empty children and cancel them.
*/
void child_kill_children (int sig)
void
child_kill_children(void)
{
size_t i, tries = 0;
if (sig != SIGTERM) return;
log_message (LOG_INFO,
"trying to bring down %zu threads...",
sblist_getsize(childs)
);
again:
for (i = 0; i < sblist_getsize(childs); i++) {
struct child *c = *((struct child**)sblist_get(childs, i));
if (!c->done) pthread_kill(c->thread, SIGCHLD);
int i;
for (i = 0; i != child_config.maxclients; i++) {
if (child_ptr[i].status != T_EMPTY)
kill(child_ptr[i].tid, SIGTERM);
}
usleep(8192);
collect_threads();
if (sblist_getsize(childs) != 0)
if(tries++ < 8) goto again;
if (sblist_getsize(childs) != 0)
log_message (LOG_CRIT,
"child_kill_children: %zu threads still alive!",
sblist_getsize(childs)
);
}
void child_free_children(void) {
sblist_free(childs);
childs = 0;
}
/**
* Listen on the various configured interfaces
*/
int child_listening_sockets(sblist *listen_addrs, uint16_t port)
int
child_listening_sock(uint16_t port)
{
int ret;
size_t i;
assert (port > 0);
if (listen_fds == NULL) {
listen_fds = sblist_new(sizeof(int), 16);
if (listen_fds == NULL) {
log_message (LOG_ERR, "Could not create the list "
"of listening fds");
return -1;
}
}
if (!listen_addrs || !sblist_getsize(listen_addrs))
{
/*
* no Listen directive:
* listen on the wildcard address(es)
*/
ret = listen_sock(NULL, port, listen_fds);
return ret;
}
for (i = 0; i < sblist_getsize(listen_addrs); i++) {
char **addr;
addr = sblist_get(listen_addrs, i);
if (!addr || !*addr) {
log_message(LOG_WARNING,
"got NULL from listen_addrs - skipping");
continue;
}
ret = listen_sock(*addr, port, listen_fds);
if (ret != 0) {
return ret;
}
}
return 0;
listenfd = listen_sock(port, &addrlen);
return listenfd;
}
void child_close_sock (void)
void
child_close_sock(void)
{
size_t i;
for (i = 0; i < sblist_getsize(listen_fds); i++) {
int *fd = sblist_get(listen_fds, i);
close (*fd);
}
sblist_free(listen_fds);
listen_fds = NULL;
close(listenfd);
}

View File

@ -1,43 +1,37 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2002 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: child.h,v 1.1.2.1 2004-06-14 20:49:57 rjkaes Exp $
*
* 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.
* See 'child.c' for more information.
*
* 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.
* Copyright (C) 2002 Robert James Kaes (rjkaes@flarenet.com)
*
* 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.
* 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, 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.
*/
/* See 'child.c' for detailed information. */
#ifndef TINYPROXY_CHILD_H
#define TINYPROXY_CHILD_H
#include "sblist.h"
typedef enum {
CHILD_MAXCLIENTS,
CHILD_MAXSPARESERVERS,
CHILD_MINSPARESERVERS,
CHILD_STARTSERVERS,
CHILD_MAXREQUESTSPERCHILD
CHILD_MAXCLIENTS,
CHILD_MAXSPARESERVERS,
CHILD_MINSPARESERVERS,
CHILD_STARTSERVERS,
CHILD_MAXREQUESTSPERCHILD
} child_config_t;
extern short int child_pool_create (void);
extern int child_listening_sockets (sblist *listen_addrs, uint16_t port);
extern void child_close_sock (void);
extern void child_main_loop (void);
extern void child_kill_children (int sig);
extern void child_free_children(void);
extern short int child_pool_create(void);
extern int child_listening_sock(uint16_t port);
extern void child_close_sock(void);
extern void child_main_loop(void);
extern void child_kill_children(void);
extern short int child_configure (child_config_t type, unsigned int val);
extern short int child_configure(child_config_t type, int val);
#endif

View File

@ -1,25 +1,21 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2002 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: common.h,v 1.6 2003-06-25 18:20:22 rjkaes Exp $
*
* 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.
*/
/* This file groups all the headers required throughout the tinyproxy
* system. All this information use to be in the "main.h" header,
* This file groups all the headers required throughout the tinyproxy
* system. All this information use to be in the "tinyproxy.h" header,
* but various other "libraries" in the program need the same information,
* without the tinyproxy specific defines.
*
* Copyright (C) 2002 Robert James Kaes (rjkaes@flarenet.com)
*
* 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, 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.
*/
#ifndef COMMON_HEADER_H
@ -32,67 +28,131 @@
/*
* Include standard headers which are used through-out tinyproxy
*/
/* standard C headers - we can safely assume they exist. */
#include <stddef.h>
#include <stdint.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* standard POSIX headers - they need to be there as well. */
# include <errno.h>
# include <fcntl.h>
# include <netdb.h>
# include <signal.h>
# include <stdarg.h>
# include <strings.h>
# include <syslog.h>
# include <wchar.h>
# include <wctype.h>
# include <sys/mman.h>
# include <sys/select.h>
# include <sys/socket.h>
# include <sys/stat.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# include <sys/wait.h>
# include <sys/uio.h>
# include <sys/un.h>
# include <sys/time.h>
# include <time.h>
#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
# include <sys/resource.h>
# include <netinet/in.h>
# include <assert.h>
# include <arpa/inet.h>
# include <grp.h>
# include <pwd.h>
# include <limits.h>
/* rest - some oddball headers */
#ifdef HAVE_VALUES_H
# include <values.h>
#endif
#ifdef HAVE_STDDEF_H
# include <stddef.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
#endif
#ifdef HAVE_SYS_UIO_H
# include <sys/uio.h>
#endif
#ifdef HAVE_SYS_UN_H
# include <sys/un.h>
#endif
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif
#ifdef HAVE_ASSERT_H
# include <assert.h>
#endif
#ifdef HAVE_CTYPE_H
# include <ctype.h>
#endif
#ifdef HAVE_ERRNO_H
# include <errno.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_GRP_H
# include <grp.h>
#endif
#ifdef HAVE_MEMORY_H
# include <memory.h>
#endif
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
#ifdef HAVE_STDARG_H
# include <stdarg.h>
#endif
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#else
# ifdef HAVE_MALLOC_H
# include <malloc.h>
# endif
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_SYSEXITS_H
# include <sysexits.h>
# include <sysexits.h>
#endif
#ifdef HAVE_SYSLOG_H
# include <syslog.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_VFORK_H
# include <vfork.h>
#endif
#ifdef HAVE_WCHAR_H
# include <wchar.h>
#endif
#ifdef HAVE_WCTYPE_H
# include <wctype.h>
#endif
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#endif
/*
@ -103,13 +163,13 @@
# define MSG_NOSIGNAL (0)
#endif
#ifndef SHUT_RD /* these three Posix.1g names are quite new */
# define SHUT_RD 0 /* shutdown for reading */
# define SHUT_WR 1 /* shutdown for writing */
# define SHUT_RDWR 2 /* shutdown for reading and writing */
#ifndef SHUT_RD /* these three Posix.1g names are quite new */
# define SHUT_RD 0 /* shutdown for reading */
# define SHUT_WR 1 /* shutdown for writing */
# define SHUT_RDWR 2 /* shutdown for reading and writing */
#endif
#define MAXLISTEN 1024 /* Max number of connections */
#define MAXLISTEN 1024 /* Max number of connections */
/*
* SunOS doesn't have INADDR_NONE defined.

View File

@ -1,72 +0,0 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include "conf-tokens.h"
#ifdef HAVE_GPERF
#include "conf-tokens-gperf.inc"
#else
#include <strings.h>
const struct config_directive_entry *
config_directive_find (register const char *str, register size_t len)
{
size_t i;
static const struct config_directive_entry wordlist[] =
{
{"",CD_NIL}, {"",CD_NIL},
{"allow", CD_allow},
{"stathost", CD_stathost},
{"listen", CD_listen},
{"timeout", CD_timeout},
{"statfile", CD_statfile},
{"pidfile", CD_pidfile},
{"bindsame", CD_bindsame},
{"reversebaseurl", CD_reversebaseurl},
{"viaproxyname", CD_viaproxyname},
{"upstream", CD_upstream},
{"anonymous", CD_anonymous},
{"group", CD_group},
{"defaulterrorfile", CD_defaulterrorfile},
{"startservers", CD_startservers},
{"filtercasesensitive", CD_filtercasesensitive},
{"filtertype", CD_filtertype},
{"filterurls", CD_filterurls},
{"filter", CD_filter},
{"reversemagic", CD_reversemagic},
{"errorfile", CD_errorfile},
{"minspareservers", CD_minspareservers},
{"user", CD_user},
{"disableviaheader", CD_disableviaheader},
{"deny", CD_deny},
{"xtinyproxy", CD_xtinyproxy},
{"reversepath", CD_reversepath},
{"bind", CD_bind},
{"maxclients", CD_maxclients},
{"reverseonly", CD_reverseonly},
{"port", CD_port},
{"maxspareservers", CD_maxspareservers},
{"syslog", CD_syslog},
{"filterdefaultdeny", CD_filterdefaultdeny},
{"loglevel", CD_loglevel},
{"filterextended", CD_filterextended},
{"connectport", CD_connectport},
{"logfile", CD_logfile},
{"basicauth", CD_basicauth},
{"basicauthrealm", CD_basicauthrealm},
{"addheader", CD_addheader},
{"maxrequestsperchild", CD_maxrequestsperchild}
};
for(i=0;i<sizeof(wordlist)/sizeof(wordlist[0]);++i) {
if(!strcasecmp(str, wordlist[i].name))
return &wordlist[i];
}
return 0;
}
#endif

View File

@ -1,63 +0,0 @@
%{
#include <string.h>
#include <stdlib.h>
#include "conf-tokens.h"
%}
struct config_directive_entry { const char* name; enum config_directive value; };
%struct-type
%define slot-name name
%define initializer-suffix ,CD_NIL
%define lookup-function-name config_directive_find
%ignore-case
%7bit
%compare-lengths
%readonly-tables
%define constants-prefix CDS_
%omit-struct-type
%%
logfile, CD_logfile
pidfile, CD_pidfile
anonymous, CD_anonymous
viaproxyname, CD_viaproxyname
defaulterrorfile, CD_defaulterrorfile
statfile, CD_statfile
stathost, CD_stathost
xtinyproxy, CD_xtinyproxy
syslog, CD_syslog
bindsame, CD_bindsame
disableviaheader, CD_disableviaheader
port, CD_port
maxclients, CD_maxclients
maxspareservers, CD_maxspareservers
minspareservers, CD_minspareservers
startservers, CD_startservers
maxrequestsperchild, CD_maxrequestsperchild
timeout, CD_timeout
connectport, CD_connectport
user, CD_user
group, CD_group
listen, CD_listen
allow, CD_allow
deny, CD_deny
bind, CD_bind
basicauth, CD_basicauth
basicauthrealm, CD_basicauthrealm
errorfile, CD_errorfile
addheader, CD_addheader
filter, CD_filter
filterurls, CD_filterurls
filterextended, CD_filterextended
filterdefaultdeny, CD_filterdefaultdeny
filtercasesensitive, CD_filtercasesensitive
filtertype, CD_filtertype
reversebaseurl, CD_reversebaseurl
reverseonly, CD_reverseonly
reversemagic, CD_reversemagic
reversepath, CD_reversepath
upstream, CD_upstream
loglevel, CD_loglevel
%%

View File

@ -1,55 +0,0 @@
#ifndef CONF_TOKENS_H
#define CONF_TOKENS_H
enum config_directive {
CD_NIL = 0,
CD_logfile,
CD_pidfile,
CD_anonymous,
CD_viaproxyname,
CD_defaulterrorfile,
CD_statfile,
CD_stathost,
CD_xtinyproxy,
CD_syslog,
CD_bindsame,
CD_disableviaheader,
CD_port,
CD_maxclients,
CD_maxspareservers,
CD_minspareservers,
CD_startservers,
CD_maxrequestsperchild,
CD_timeout,
CD_connectport,
CD_user,
CD_group,
CD_listen,
CD_allow,
CD_deny,
CD_bind,
CD_basicauth,
CD_basicauthrealm,
CD_errorfile,
CD_addheader,
CD_filter,
CD_filterurls,
CD_filtertype,
CD_filterextended,
CD_filterdefaultdeny,
CD_filtercasesensitive,
CD_reversebaseurl,
CD_reverseonly,
CD_reversemagic,
CD_reversepath,
CD_upstream,
CD_loglevel,
};
struct config_directive_entry { const char* name; enum config_directive value; };
const struct config_directive_entry *
config_directive_find (register const char *str, register size_t len);
#endif

1154
src/conf.c

File diff suppressed because it is too large Load Diff

View File

@ -1,120 +0,0 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2004 Robert James Kaes <rjkaes@users.sourceforge.net>
* Copyright (C) 2009 Michael Adam <obnox@samba.org>
*
* 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 'conf.c' for detailed information. */
#ifndef TINYPROXY_CONF_H
#define TINYPROXY_CONF_H
#include "hsearch.h"
#include "sblist.h"
#include "acl.h"
/*
* Stores a HTTP header created using the AddHeader directive.
*/
typedef struct {
char *name;
char *value;
} http_header_t;
/*
* Hold all the configuration time information.
*/
struct config_s {
sblist *basicauth_list;
char *basicauth_realm;
char *logf_name;
unsigned int syslog; /* boolean */
unsigned int port;
char *stathost;
unsigned int quit; /* boolean */
unsigned int maxclients;
char *user;
char *group;
sblist *listen_addrs;
#ifdef FILTER_ENABLE
char *filter;
unsigned int filter_opts; /* enum filter_options */
#endif /* FILTER_ENABLE */
#ifdef XTINYPROXY_ENABLE
unsigned int add_xtinyproxy; /* boolean */
#endif
#ifdef REVERSE_SUPPORT
struct reversepath *reversepath_list;
unsigned int reverseonly; /* boolean */
unsigned int reversemagic; /* boolean */
char *reversebaseurl;
#endif
#ifdef UPSTREAM_SUPPORT
struct upstream *upstream_list;
#endif /* UPSTREAM_SUPPORT */
char *pidpath;
unsigned int idletimeout;
sblist *bind_addrs;
unsigned int bindsame;
/*
* The configured name to use in the HTTP "Via" header field.
*/
char *via_proxy_name;
unsigned int disable_viaheader; /* boolean */
/*
* Error page support. Map error numbers to file paths.
*/
struct htab *errorpages;
/*
* Error page to be displayed if appropriate page cannot be located
* in the errorpages structure.
*/
char *errorpage_undef;
/*
* The HTML statistics page.
*/
char *statpage;
acl_list_t access_list;
/*
* Store the list of port allowed by CONNECT.
*/
sblist *connect_ports;
/*
* Map of headers which should be let through when the
* anonymous feature is turned on.
*/
struct htab *anonymous_map;
/*
* Extra headers to be added to outgoing HTTP requests.
*/
sblist* add_headers;
};
extern int reload_config_file (const char *config_fname, struct config_s *conf);
int config_init (void);
void free_config (struct config_s *conf);
#endif

View File

@ -1,77 +0,0 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 1998 Steven Young <sdyoung@miranda.org>
* Copyright (C) 1999-2005 Robert James Kaes <rjkaes@users.sourceforge.net>
* Copyright (C) 2009 Michael Adam <obnox@samba.org>
*
* 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 "connect-ports.h"
#include "log.h"
/*
* Now, this routine adds a "port" to the list. It also creates the list if
* it hasn't already by done.
*/
void add_connect_port_allowed (int port, sblist **connect_ports)
{
if (!*connect_ports) {
*connect_ports = sblist_new (sizeof(int), 16);
if (!*connect_ports) {
log_message (LOG_WARNING,
"Could not create a list of allowed CONNECT ports");
return;
}
}
log_message (LOG_INFO,
"Adding Port [%d] to the list allowed by CONNECT", port);
sblist_add (*connect_ports, &port);
}
/*
* This routine checks to see if a port is allowed in the CONNECT method.
*
* Returns: 1 if allowed
* 0 if denied
*/
int check_allowed_connect_ports (int port, sblist *connect_ports)
{
size_t i;
int *data;
/*
* The absence of ConnectPort options in the config file
* meanas that all ports are allowed for CONNECT.
*/
if (!connect_ports)
return 1;
for (i = 0; i < sblist_getsize (connect_ports); ++i) {
data = sblist_get (connect_ports, i);
if (data && *data == port)
return 1;
}
return 0;
}
/**
* Free a connect_ports list.
*/
void free_connect_ports_list (sblist *connect_ports)
{
sblist_free (connect_ports);
}

View File

@ -1,31 +0,0 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 1998 Steven Young <sdyoung@miranda.org>
* Copyright (C) 1999 Robert James Kaes <rjkaes@users.sourceforge.net>
* Copyright (C) 2009 Michael Adam <obnox@samba.org>
*
* 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.
*/
#ifndef _TINYPROXY_CONNECT_PORTS_H_
#define _TINYPROXY_CONNECT_PORTS_H_
#include "common.h"
#include "sblist.h"
extern void add_connect_port_allowed (int port, sblist **connect_ports);
int check_allowed_connect_ports (int port, sblist *connect_ports);
void free_connect_ports_list (sblist *connect_ports);
#endif /* _TINYPROXY_CONNECT_PORTS_ */

View File

@ -1,28 +1,24 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2001 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: conns.c,v 1.17.2.1 2004-08-06 16:56:55 rjkaes Exp $
*
* 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.
*/
/* Create and free the connection structure. One day there could be
* Create and free the connection structure. One day there could be
* other connection related tasks put here, but for now the header
* file and this file are only used for create/free functions and the
* connection structure definition.
*
* Copyright (C) 2001 Robert James Kaes (rjkaes@flarenet.com)
*
* 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, 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.
*/
#include "main.h"
#include "tinyproxy.h"
#include "buffer.h"
#include "conns.h"
@ -30,99 +26,116 @@
#include "log.h"
#include "stats.h"
void conn_struct_init(struct conn_s *connptr) {
connptr->error_number = -1;
connptr->client_fd = -1;
connptr->server_fd = -1;
/* There is _no_ content length initially */
connptr->content_length.server = connptr->content_length.client = -1;
}
int conn_init_contents (struct conn_s *connptr, const char *ipaddr,
const char *sock_ipaddr)
struct conn_s *
initialize_conn(int client_fd, const char* ipaddr, const char* string_addr)
{
struct buffer_s *cbuffer, *sbuffer;
struct conn_s *connptr;
struct buffer_s *cbuffer, *sbuffer;
assert (connptr->client_fd >= 0);
assert(client_fd >= 0);
/*
* Allocate the memory for all the internal components
*/
cbuffer = new_buffer ();
sbuffer = new_buffer ();
/*
* Allocate the memory for all the internal components
*/
cbuffer = new_buffer();
sbuffer = new_buffer();
if (!cbuffer || !sbuffer)
goto error_exit;
if (!cbuffer || !sbuffer)
goto error_exit;
connptr->cbuffer = cbuffer;
connptr->sbuffer = sbuffer;
/*
* Allocate the space for the conn_s structure itself.
*/
connptr = safemalloc(sizeof(struct conn_s));
if (!connptr)
goto error_exit;
connptr->server_ip_addr = (sock_ipaddr ?
safestrdup (sock_ipaddr) : NULL);
connptr->client_ip_addr = safestrdup (ipaddr);
connptr->client_fd = client_fd;
connptr->server_fd = -1;
update_stats (STAT_OPEN);
connptr->cbuffer = cbuffer;
connptr->sbuffer = sbuffer;
return 1;
connptr->request_line = NULL;
/* These store any error strings */
connptr->error_variables = NULL;
connptr->error_variable_count = 0;
connptr->error_string = NULL;
connptr->error_number = -1;
connptr->connect_method = FALSE;
connptr->show_stats = FALSE;
connptr->protocol.major = connptr->protocol.minor = 0;
/* There is _no_ content length initially */
connptr->content_length.server = connptr->content_length.client = -1;
connptr->client_ip_addr = safestrdup(ipaddr);
connptr->client_string_addr = safestrdup(string_addr);
connptr->upstream_proxy = NULL;
update_stats(STAT_OPEN);
return connptr;
error_exit:
/*
* If we got here, there was a problem allocating memory
*/
if (cbuffer)
delete_buffer (cbuffer);
if (sbuffer)
delete_buffer (sbuffer);
/*
* If we got here, there was a problem allocating memory
*/
if (cbuffer)
delete_buffer(cbuffer);
if (sbuffer)
delete_buffer(sbuffer);
return 0;
return NULL;
}
void conn_destroy_contents (struct conn_s *connptr)
void
destroy_conn(struct conn_s *connptr)
{
assert (connptr != NULL);
assert(connptr != NULL);
if (connptr->client_fd != -1)
if (close (connptr->client_fd) < 0)
log_message (LOG_INFO, "Client (%d) close message: %s",
connptr->client_fd, strerror (errno));
connptr->client_fd = -1;
if (connptr->server_fd != -1)
if (close (connptr->server_fd) < 0)
log_message (LOG_INFO, "Server (%d) close message: %s",
connptr->server_fd, strerror (errno));
connptr->server_fd = -1;
if (connptr->client_fd != -1)
if (close(connptr->client_fd) < 0)
log_message(LOG_INFO, "Client (%d) close message: %s",
connptr->client_fd, strerror(errno));
if (connptr->server_fd != -1)
if (close(connptr->server_fd) < 0)
log_message(LOG_INFO, "Server (%d) close message: %s",
connptr->server_fd, strerror(errno));
if (connptr->cbuffer)
delete_buffer (connptr->cbuffer);
if (connptr->sbuffer)
delete_buffer (connptr->sbuffer);
if (connptr->cbuffer)
delete_buffer(connptr->cbuffer);
if (connptr->sbuffer)
delete_buffer(connptr->sbuffer);
if (connptr->request_line)
safefree (connptr->request_line);
if (connptr->request_line)
safefree(connptr->request_line);
if (connptr->error_variables) {
char *k;
htab_value *v;
size_t it = 0;
while((it = htab_next(connptr->error_variables, it, &k, &v))) {
safefree(v->p);
safefree(k);
}
htab_destroy (connptr->error_variables);
}
if (connptr->error_variables) {
int i;
if (connptr->error_string)
safefree (connptr->error_string);
for (i = 0; i != connptr->error_variable_count; ++i) {
safefree(connptr->error_variables[i]->error_key);
safefree(connptr->error_variables[i]->error_val);
safefree(connptr->error_variables[i]);
}
if (connptr->server_ip_addr)
safefree (connptr->server_ip_addr);
if (connptr->client_ip_addr)
safefree (connptr->client_ip_addr);
safefree(connptr->error_variables);
}
#ifdef REVERSE_SUPPORT
if (connptr->reversepath)
safefree (connptr->reversepath);
#endif
if (connptr->error_string)
safefree(connptr->error_string);
update_stats (STAT_CLOSE);
if (connptr->client_ip_addr)
safefree(connptr->client_ip_addr);
if (connptr->client_string_addr)
safefree(connptr->client_string_addr);
safefree(connptr);
update_stats(STAT_CLOSE);
}

View File

@ -1,99 +1,86 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2001 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: conns.h,v 1.14.2.1 2004-08-06 16:56:55 rjkaes Exp $
*
* 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.
* See 'conns.c' for a detailed description.
*
* 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.
* Copyright (C) 2001 Robert James Kaes (rjkaes@flarenet.com)
*
* 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.
* 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, 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.
*/
/* See 'conns.c' for detailed information. */
#ifndef TINYPROXY_CONNS_H
#define TINYPROXY_CONNS_H
#include "main.h"
#include "hsearch.h"
#include "tinyproxy.h"
/*
* Connection Definition
*/
struct conn_s {
int client_fd;
int server_fd;
int client_fd;
int server_fd;
struct buffer_s *cbuffer;
struct buffer_s *sbuffer;
struct buffer_s *cbuffer;
struct buffer_s *sbuffer;
/* The request line (first line) from the client */
char *request_line;
/* The request line (first line) from the client */
char *request_line;
/* Booleans */
unsigned int connect_method;
unsigned int show_stats;
/* Booleans */
unsigned int connect_method;
unsigned int show_stats;
/*
* This structure stores key -> value mappings for substitution
* in the error HTML files.
*/
struct htab *error_variables;
/*
* Store the error response if there is one.
* This structure stores key -> value mappings for substitution
* in the error HTML files.
*/
struct error_variable_s {
char *error_key;
char *error_val;
} **error_variables;
int error_variable_count;
int error_number;
char *error_string;
int error_number;
char *error_string;
/* A Content-Length value from the remote server */
struct {
long int server;
long int client;
} content_length;
/* A Content-Length value from the remote server */
struct {
long int server;
long int client;
} content_length;
/*
* Store the server's IP (for BindSame)
*/
char *server_ip_addr;
/*
* Store the client's IP information
*/
char *client_ip_addr;
/*
* Store the incoming request's HTTP protocol.
*/
struct {
unsigned int major;
unsigned int minor;
} protocol;
#ifdef REVERSE_SUPPORT
/*
* Place to store the current per-connection reverse proxy path
*/
char *reversepath;
#endif
/*
* Store the client's IP and hostname information
*/
char* client_ip_addr;
char* client_string_addr;
/*
* Store the incoming request's HTTP protocol.
*/
struct {
unsigned int major;
unsigned int minor;
} protocol;
/*
* Pointer to upstream proxy.
*/
struct upstream *upstream_proxy;
};
/* expects pointer to zero-initialized struct, set up struct
with default values for initial use */
extern void conn_struct_init(struct conn_s *connptr);
/* second stage initializiation, sets up buffers and connection details */
extern int conn_init_contents (struct conn_s *connptr, const char *ipaddr,
const char *sock_ipaddr);
extern void conn_destroy_contents (struct conn_s *connptr);
/*
* Functions for the creation and destruction of a connection structure.
*/
extern struct conn_s* initialize_conn(int client_fd, const char* ipaddr,
const char* string_addr);
extern void destroy_conn(struct conn_s *connptr);
#endif

View File

@ -1,61 +1,53 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2002 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: daemon.c,v 1.2.2.1 2004-08-10 03:38:13 rjkaes Exp $
*
* 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.
*/
/* This file contains functions which are useful when writing a
* This file contains functions which are useful when writing a
* daemon process. The functions include a "makedaemon" function and
* a function to portably set a signal handler.
*
* Copyright (C) 2002 Robert James Kaes (rjkaes@flarenet.com)
*
* 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, 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.
*/
#include "main.h"
#include "tinyproxy.h"
#include "daemon.h"
#include "log.h"
/*
* Fork a child process and then kill the parent so make the calling
* program a daemon process.
*/
void makedaemon (void)
void
makedaemon(void)
{
if (fork () != 0)
exit (0);
if (fork() != 0)
exit(0);
setsid ();
set_signal_handler (SIGHUP, SIG_IGN);
setsid();
set_signal_handler(SIGHUP, SIG_IGN);
if (fork () != 0)
exit (0);
if (fork() != 0)
exit(0);
if (chdir ("/") != 0) {
log_message (LOG_WARNING,
"Could not change directory to /");
}
chdir("/");
umask(0177);
umask (0177);
#ifdef NDEBUG
#if NDEBUG
/*
* When not in debugging mode, close the standard file
* descriptors.
*/
close (0);
close (1);
close (2);
close(0);
close(1);
close(2);
#endif
}
@ -63,25 +55,26 @@ void makedaemon (void)
* Pass a signal number and a signal handling function into this function
* to handle signals sent to the process.
*/
signal_func *set_signal_handler (int signo, signal_func * func)
signal_func *
set_signal_handler(int signo, signal_func *func)
{
struct sigaction act, oact;
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
if (signo == SIGALRM) {
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo == SIGALRM) {
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
#endif
} else {
} else {
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART; /* SVR4, 4.4BSD */
act.sa_flags |= SA_RESTART; /* SVR4, 4.4BSD */
#endif
}
}
if (sigaction (signo, &act, &oact) < 0)
return SIG_ERR;
if (sigaction(signo, &act, &oact) < 0)
return SIG_ERR;
return oact.sa_handler;
return oact.sa_handler;
}

View File

@ -1,36 +1,33 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2002 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: daemon.h,v 1.1 2002-05-23 04:39:32 rjkaes Exp $
*
* 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.
* See 'daemon.c' for a detailed description.
*
* 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.
* Copyright (C) 2002 Robert James Kaes (rjkaes@flarenet.com)
*
* 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.
* 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, 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.
*/
/* See 'daemon.c' for detailed information. */
#ifndef TINYPROXY_DAEMON_H
#define TINYPROXY_DAEMON_H
typedef void signal_func (int);
typedef void signal_func(int);
/*
* Pass a singal integer and a function to handle the signal.
*/
extern signal_func *set_signal_handler (int signo, signal_func * func);
extern signal_func *set_signal_handler(int signo, signal_func *func);
/*
* Make a program a daemon process
*/
extern void makedaemon (void);
extern void makedaemon(void);
#endif

View File

@ -1,207 +1,210 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 1999 George Talusan <gstalusan@uwaterloo.ca>
* Copyright (C) 2002 James E. Flemer <jflemer@acm.jhu.edu>
* Copyright (C) 2002 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: filter.c,v 1.16.2.1 2003-10-16 21:19:09 rjkaes Exp $
*
* 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.
* Copyright (c) 1999 George Talusan (gstalusan@uwaterloo.ca)
* Copyright (c) 2002 James E. Flemer (jflemer@acm.jhu.edu)
* Copyright (c) 2002 Robert James Kaes (rjkaes@flarenet.com)
*
* 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.
*/
/* A substring of the domain to be filtered goes into the file
* A substring of the domain to be filtered goes into the file
* pointed at by DEFAULT_FILTER.
*
* 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, 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.
*/
#include "main.h"
#include "tinyproxy.h"
#include <regex.h>
#include <fnmatch.h>
#include "filter.h"
#include "heap.h"
#include "log.h"
#include "regexp.h"
#include "reqs.h"
#include "conf.h"
#include "sblist.h"
#define FILTER_BUFFER_LEN (512)
static int err;
struct filter_list {
union {
regex_t cpatb;
char *pattern;
} u;
struct filter_list *next;
char *pat;
regex_t *cpat;
};
static sblist *fl = NULL;
static struct filter_list *fl = NULL;
static int already_init = 0;
static filter_policy_t default_policy = FILTER_DEFAULT_ALLOW;
/*
* Initializes a list of strings containing hosts/urls to be filtered
* Initializes a linked list of strings containing hosts/urls to be filtered
*/
void filter_init (void)
void
filter_init(void)
{
FILE *fd;
struct filter_list fe;
char buf[FILTER_BUFFER_LEN];
char *s, *start;
int cflags, lineno = 0;
FILE *fd;
struct filter_list *p;
char buf[FILTER_BUFFER_LEN];
char *s;
int cflags;
if (fl || already_init) {
return;
}
if (!fl && !already_init) {
fd = fopen(config.filter, "r");
if (fd) {
p = NULL;
fd = fopen (config->filter, "r");
if (!fd) {
perror ("filter file");
exit (EX_DATAERR);
}
cflags = REG_NEWLINE | REG_NOSUB;
if (config.filter_extended)
cflags |= REG_EXTENDED;
if (!config.filter_casesensitive)
cflags |= REG_ICASE;
cflags = REG_NEWLINE | REG_NOSUB;
cflags |= (REG_EXTENDED * !!(config->filter_opts & FILTER_OPT_TYPE_ERE));
cflags |= (REG_ICASE * !(config->filter_opts & FILTER_OPT_CASESENSITIVE));
while (fgets(buf, FILTER_BUFFER_LEN, fd)) {
/*
* Remove any trailing white space and
* comments.
*/
s = buf;
while (*s) {
if (isspace((unsigned char)*s)) break;
if (*s == '#') {
/*
* If the '#' char is preceeded by
* an escape, it's not a comment
* string.
*/
if (s == buf || *(s - 1) != '\\')
break;
}
++s;
}
*s = '\0';
while (fgets (buf, FILTER_BUFFER_LEN, fd)) {
++lineno;
/* skip leading whitespace */
s = buf;
while (*s && isspace ((unsigned char) *s))
s++;
start = s;
/* skip leading whitespace */
s = buf;
while (*s && isspace((unsigned char)*s))
s++;
/*
* Remove any trailing white space and
* comments.
*/
while (*s) {
if (isspace ((unsigned char) *s))
break;
if (*s == '#') {
/*
* If the '#' char is preceeded by
* an escape, it's not a comment
* string.
*/
if (s == buf || *(s - 1) != '\\')
break;
}
++s;
}
*s = '\0';
s = start;
/* skip blank lines and comments */
if (*s == '\0')
continue;
/* skip blank lines and comments */
if (*s == '\0')
continue;
if (!p) /* head of list */
fl = p =
safecalloc(1,
sizeof(struct
filter_list));
else { /* next entry */
p->next =
safecalloc(1,
sizeof(struct
filter_list));
p = p->next;
}
if (!fl) fl = sblist_new(sizeof(struct filter_list),
4096/sizeof(struct filter_list));
p->pat = safestrdup(s);
p->cpat = safemalloc(sizeof(regex_t));
if ((err = regcomp(p->cpat, p->pat, cflags)) != 0) {
fprintf(stderr, "Bad regex in %s: %s\n",
config.filter, p->pat);
exit(EX_DATAERR);
}
}
if (ferror(fd)) {
perror("fgets");
exit(EX_DATAERR);
}
fclose(fd);
if (config->filter_opts & FILTER_OPT_TYPE_FNMATCH) {
fe.u.pattern = safestrdup(s);
if (!fe.u.pattern) goto oom;
} else {
err = regcomp (&fe.u.cpatb, s, cflags);
if (err != 0) {
if (err == REG_ESPACE) goto oom;
fprintf (stderr,
"Bad regex in %s: line %d - %s\n",
config->filter, lineno, s);
exit (EX_DATAERR);
}
}
if (!sblist_add(fl, &fe)) {
oom:;
fprintf (stderr,
"out of memory parsing filter file %s: line %d\n",
config->filter, lineno);
exit (EX_DATAERR);
}
}
if (ferror (fd)) {
perror ("fgets");
exit (EX_DATAERR);
}
fclose (fd);
already_init = 1;
already_init = 1;
}
}
}
/* unlink the list */
void filter_destroy (void)
void
filter_destroy(void)
{
struct filter_list *p;
size_t i;
struct filter_list *p, *q;
if (already_init) {
if (fl) {
for (i = 0; i < sblist_getsize(fl); ++i) {
p = sblist_get(fl, i);
if (config->filter_opts & FILTER_OPT_TYPE_FNMATCH)
safefree(p->u.pattern);
else
regfree (&p->u.cpatb);
}
sblist_free(fl);
}
fl = NULL;
already_init = 0;
}
}
/**
* reload the filter file if filtering is enabled
*/
void filter_reload (void)
{
if (config->filter) {
log_message (LOG_NOTICE, "Re-reading filter file.");
filter_destroy ();
filter_init ();
}
if (already_init) {
for (p = q = fl; p; p = q) {
regfree(p->cpat);
safefree(p->cpat);
safefree(p->pat);
q = p->next;
safefree(p);
}
fl = NULL;
already_init = 0;
}
}
/* Return 0 to allow, non-zero to block */
int filter_run (const char *str)
int
filter_domain(const char *host)
{
struct filter_list *p;
size_t i;
int result;
struct filter_list *p;
int result;
if (!fl || !already_init)
goto COMMON_EXIT;
if (!fl || !already_init)
goto COMMON_EXIT;
for (i = 0; i < sblist_getsize(fl); ++i) {
p = sblist_get(fl, i);
if (config->filter_opts & FILTER_OPT_TYPE_FNMATCH)
result = fnmatch (p->u.pattern, str, 0);
else
result =
regexec (&p->u.cpatb, str, (size_t) 0, (regmatch_t *) 0, 0);
for (p = fl; p; p = p->next) {
result = regexec(p->cpat, host, (size_t) 0, (regmatch_t *) 0, 0);
if (result == 0) {
if (!(config->filter_opts & FILTER_OPT_DEFAULT_DENY))
return 1;
else
return 0;
}
}
if (result == 0) {
if (default_policy == FILTER_DEFAULT_ALLOW)
return 1;
else
return 0;
}
}
COMMON_EXIT:
if (!(config->filter_opts & FILTER_OPT_DEFAULT_DENY))
return 0;
else
return 1;
COMMON_EXIT:
if (default_policy == FILTER_DEFAULT_ALLOW)
return 0;
else
return 1;
}
/* returns 0 to allow, non-zero to block */
int
filter_url(const char *url)
{
struct filter_list *p;
int result;
if (!fl || !already_init)
goto COMMON_EXIT;
for (p = fl; p; p = p->next) {
result = regexec(p->cpat, url, (size_t) 0, (regmatch_t *) 0, 0);
if (result == 0) {
if (default_policy == FILTER_DEFAULT_ALLOW)
return 1;
else
return 0;
}
}
COMMON_EXIT:
if (default_policy == FILTER_DEFAULT_ALLOW)
return 0;
else
return 1;
}
/*
* Set the default filtering policy
*/
void
filter_set_default_policy(filter_policy_t policy)
{
default_policy = policy;
}

View File

@ -1,42 +1,33 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 1999 George Talusan <gstalusan@uwaterloo.ca>
/* $Id: filter.h,v 1.5 2002-06-07 18:36:21 rjkaes Exp $
*
* 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.
* See 'filter.c' for a detailed description.
*
* 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.
* Copyright (c) 1999 George Talusan (gstalusan@uwaterloo.ca)
*
* 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.
* 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, 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.
*/
/* See 'filter.c' for detailed information. */
#ifndef _TINYPROXY_FILTER_H_
#define _TINYPROXY_FILTER_H_
enum filter_options {
FILTER_OPT_CASESENSITIVE = 1 << 0,
FILTER_OPT_URL = 1 << 1,
FILTER_OPT_DEFAULT_DENY = 1 << 2,
typedef enum {
FILTER_DEFAULT_ALLOW,
FILTER_DEFAULT_DENY,
} filter_policy_t;
FILTER_OPT_TYPE_BRE = 1 << 8,
FILTER_OPT_TYPE_ERE = 1 << 9,
FILTER_OPT_TYPE_FNMATCH = 1 << 10,
};
extern void filter_init(void);
extern void filter_destroy(void);
extern int filter_domain(const char *host);
extern int filter_url(const char *url);
#define FILTER_TYPE_MASK \
(FILTER_OPT_TYPE_BRE | FILTER_OPT_TYPE_ERE | FILTER_OPT_TYPE_FNMATCH)
extern void filter_init (void);
extern void filter_destroy (void);
extern void filter_reload (void);
extern int filter_run (const char *str);
extern void filter_set_default_policy(filter_policy_t policy);
#endif

5880
src/gnuregex.c Normal file

File diff suppressed because it is too large Load Diff

542
src/gnuregex.h Normal file
View File

@ -0,0 +1,542 @@
/* Definitions for data structures and routines for the regular
expression library, version 0.12.
Copyright (C) 1985,89,90,91,92,93,95,96,97,98 Free Software Foundation, Inc.
This file is part of the GNU C Library. Its master source is NOT part of
the C library, however. The master source lives in /gd/gnu/lib.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _REGEX_H
#define _REGEX_H 1
/* Allow the use in C++ code. */
#ifdef __cplusplus
extern "C" {
#endif
/* POSIX says that <sys/types.h> must be included (by the caller) before
<regex.h>. */
#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS
/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
should be there. */
# include <stddef.h>
#endif
/* The following two types have to be signed and unsigned integer type
wide enough to hold a value of a pointer. For most ANSI compilers
ptrdiff_t and size_t should be likely OK. Still size of these two
types is 2 for Microsoft C. Ugh... */
typedef long int s_reg_t;
typedef unsigned long int active_reg_t;
/* The following bits are used to determine the regexp syntax we
recognize. The set/not-set meanings are chosen so that Emacs syntax
remains the value 0. The bits are given in alphabetical order, and
the definitions shifted by one from the previous bit; thus, when we
add or remove a bit, only one other definition need change. */
typedef unsigned long int reg_syntax_t;
/* If this bit is not set, then \ inside a bracket expression is literal.
If set, then such a \ quotes the following character. */
#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
/* If this bit is not set, then + and ? are operators, and \+ and \? are
literals.
If set, then \+ and \? are operators and + and ? are literals. */
#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
/* If this bit is set, then character classes are supported. They are:
[:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
[:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
If not set, then character classes are not supported. */
#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
/* If this bit is set, then ^ and $ are always anchors (outside bracket
expressions, of course).
If this bit is not set, then it depends:
^ is an anchor if it is at the beginning of a regular
expression or after an open-group or an alternation operator;
$ is an anchor if it is at the end of a regular expression, or
before a close-group or an alternation operator.
This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
POSIX draft 11.2 says that * etc. in leading positions is undefined.
We already implemented a previous draft which made those constructs
invalid, though, so we haven't changed the code back. */
#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
/* If this bit is set, then special characters are always special
regardless of where they are in the pattern.
If this bit is not set, then special characters are special only in
some contexts; otherwise they are ordinary. Specifically,
* + ? and intervals are only special when not after the beginning,
open-group, or alternation operator. */
#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
/* If this bit is set, then *, +, ?, and { cannot be first in an re or
immediately after an alternation or begin-group operator. */
#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
/* If this bit is set, then . matches newline.
If not set, then it doesn't. */
#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
/* If this bit is set, then . doesn't match NUL.
If not set, then it does. */
#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
/* If this bit is set, nonmatching lists [^...] do not match newline.
If not set, they do. */
#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
/* If this bit is set, either \{...\} or {...} defines an
interval, depending on RE_NO_BK_BRACES.
If not set, \{, \}, {, and } are literals. */
#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
/* If this bit is set, +, ? and | aren't recognized as operators.
If not set, they are. */
#define RE_LIMITED_OPS (RE_INTERVALS << 1)
/* If this bit is set, newline is an alternation operator.
If not set, newline is literal. */
#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
/* If this bit is set, then `{...}' defines an interval, and \{ and \}
are literals.
If not set, then `\{...\}' defines an interval. */
#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
/* If this bit is set, (...) defines a group, and \( and \) are literals.
If not set, \(...\) defines a group, and ( and ) are literals. */
#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
/* If this bit is set, then \<digit> matches <digit>.
If not set, then \<digit> is a back-reference. */
#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
/* If this bit is set, then | is an alternation operator, and \| is literal.
If not set, then \| is an alternation operator, and | is literal. */
#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
/* If this bit is set, then an ending range point collating higher
than the starting range point, as in [z-a], is invalid.
If not set, then when ending range point collates higher than the
starting range point, the range is ignored. */
#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
/* If this bit is set, then an unmatched ) is ordinary.
If not set, then an unmatched ) is invalid. */
#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
/* If this bit is set, succeed as soon as we match the whole pattern,
without further backtracking. */
#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
/* If this bit is set, do not process the GNU regex operators.
If not set, then the GNU regex operators are recognized. */
#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
/* If this bit is set, turn on internal regex debugging.
If not set, and debugging was on, turn it off.
This only works if regex.c is compiled -DDEBUG.
We define this bit always, so that all that's needed to turn on
debugging is to recompile regex.c; the calling code can always have
this bit set, and it won't affect anything in the normal case. */
#define RE_DEBUG (RE_NO_GNU_OPS << 1)
/* This global variable defines the particular regexp syntax to use (for
some interfaces). When a regexp is compiled, the syntax used is
stored in the pattern buffer, so changing this does not affect
already-compiled regexps. */
extern reg_syntax_t re_syntax_options;
/* Define combinations of the above bits for the standard possibilities.
(The [[[ comments delimit what gets put into the Texinfo file, so
don't delete them!) */
/* [[[begin syntaxes]]] */
#define RE_SYNTAX_EMACS 0
#define RE_SYNTAX_AWK \
(RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
| RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
| RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
#define RE_SYNTAX_GNU_AWK \
((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
& ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS))
#define RE_SYNTAX_POSIX_AWK \
(RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
| RE_INTERVALS | RE_NO_GNU_OPS)
#define RE_SYNTAX_GREP \
(RE_BK_PLUS_QM | RE_CHAR_CLASSES \
| RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
| RE_NEWLINE_ALT)
#define RE_SYNTAX_EGREP \
(RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
| RE_NEWLINE_ALT | RE_NO_BK_PARENS \
| RE_NO_BK_VBAR)
#define RE_SYNTAX_POSIX_EGREP \
(RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
/* Syntax bits common to both basic and extended POSIX regex syntax. */
#define _RE_SYNTAX_POSIX_COMMON \
(RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
| RE_INTERVALS | RE_NO_EMPTY_RANGES)
#define RE_SYNTAX_POSIX_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
isn't minimal, since other operators, such as \`, aren't disabled. */
#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
#define RE_SYNTAX_POSIX_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_VBAR \
| RE_UNMATCHED_RIGHT_PAREN_ORD)
/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */
#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
/* [[[end syntaxes]]] */
/* Maximum number of duplicates an interval can allow. Some systems
(erroneously) define this in other header files, but we want our
value, so remove any previous define. */
#ifdef RE_DUP_MAX
# undef RE_DUP_MAX
#endif
/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
#define RE_DUP_MAX (0x7fff)
/* POSIX `cflags' bits (i.e., information for `regcomp'). */
/* If this bit is set, then use extended regular expression syntax.
If not set, then use basic regular expression syntax. */
#define REG_EXTENDED 1
/* If this bit is set, then ignore case when matching.
If not set, then case is significant. */
#define REG_ICASE (REG_EXTENDED << 1)
/* If this bit is set, then anchors do not match at newline
characters in the string.
If not set, then anchors do match at newlines. */
#define REG_NEWLINE (REG_ICASE << 1)
/* If this bit is set, then report only success or fail in regexec.
If not set, then returns differ between not matching and errors. */
#define REG_NOSUB (REG_NEWLINE << 1)
/* POSIX `eflags' bits (i.e., information for regexec). */
/* If this bit is set, then the beginning-of-line operator doesn't match
the beginning of the string (presumably because it's not the
beginning of a line).
If not set, then the beginning-of-line operator does match the
beginning of the string. */
#define REG_NOTBOL 1
/* Like REG_NOTBOL, except for the end-of-line. */
#define REG_NOTEOL (1 << 1)
/* If any error codes are removed, changed, or added, update the
`re_error_msg' table in regex.c. */
typedef enum
{
#ifdef _XOPEN_SOURCE
REG_ENOSYS = -1, /* This will never happen for this implementation. */
#endif
REG_NOERROR = 0, /* Success. */
REG_NOMATCH, /* Didn't find a match (for regexec). */
/* POSIX regcomp return error codes. (In the order listed in the
standard.) */
REG_BADPAT, /* Invalid pattern. */
REG_ECOLLATE, /* Not implemented. */
REG_ECTYPE, /* Invalid character class name. */
REG_EESCAPE, /* Trailing backslash. */
REG_ESUBREG, /* Invalid back reference. */
REG_EBRACK, /* Unmatched left bracket. */
REG_EPAREN, /* Parenthesis imbalance. */
REG_EBRACE, /* Unmatched \{. */
REG_BADBR, /* Invalid contents of \{\}. */
REG_ERANGE, /* Invalid range end. */
REG_ESPACE, /* Ran out of memory. */
REG_BADRPT, /* No preceding re for repetition op. */
/* Error codes we've added. */
REG_EEND, /* Premature end. */
REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
} reg_errcode_t;
/* This data structure represents a compiled pattern. Before calling
the pattern compiler, the fields `buffer', `allocated', `fastmap',
`translate', and `no_sub' can be set. After the pattern has been
compiled, the `re_nsub' field is available. All other fields are
private to the regex routines. */
#ifndef RE_TRANSLATE_TYPE
# define RE_TRANSLATE_TYPE char *
#endif
struct re_pattern_buffer
{
/* [[[begin pattern_buffer]]] */
/* Space that holds the compiled pattern. It is declared as
`unsigned char *' because its elements are
sometimes used as array indexes. */
unsigned char *buffer;
/* Number of bytes to which `buffer' points. */
unsigned long int allocated;
/* Number of bytes actually used in `buffer'. */
unsigned long int used;
/* Syntax setting with which the pattern was compiled. */
reg_syntax_t syntax;
/* Pointer to a fastmap, if any, otherwise zero. re_search uses
the fastmap, if there is one, to skip over impossible
starting points for matches. */
char *fastmap;
/* Either a translate table to apply to all characters before
comparing them, or zero for no translation. The translation
is applied to a pattern when it is compiled and to a string
when it is matched. */
RE_TRANSLATE_TYPE translate;
/* Number of subexpressions found by the compiler. */
size_t re_nsub;
/* Zero if this pattern cannot match the empty string, one else.
Well, in truth it's used only in `re_search_2', to see
whether or not we should use the fastmap, so we don't set
this absolutely perfectly; see `re_compile_fastmap' (the
`duplicate' case). */
unsigned can_be_null : 1;
/* If REGS_UNALLOCATED, allocate space in the `regs' structure
for `max (RE_NREGS, re_nsub + 1)' groups.
If REGS_REALLOCATE, reallocate space if necessary.
If REGS_FIXED, use what's there. */
#define REGS_UNALLOCATED 0
#define REGS_REALLOCATE 1
#define REGS_FIXED 2
unsigned regs_allocated : 2;
/* Set to zero when `regex_compile' compiles a pattern; set to one
by `re_compile_fastmap' if it updates the fastmap. */
unsigned fastmap_accurate : 1;
/* If set, `re_match_2' does not return information about
subexpressions. */
unsigned no_sub : 1;
/* If set, a beginning-of-line anchor doesn't match at the
beginning of the string. */
unsigned not_bol : 1;
/* Similarly for an end-of-line anchor. */
unsigned not_eol : 1;
/* If true, an anchor at a newline matches. */
unsigned newline_anchor : 1;
/* [[[end pattern_buffer]]] */
};
typedef struct re_pattern_buffer regex_t;
/* Type for byte offsets within the string. POSIX mandates this. */
typedef int regoff_t;
/* This is the structure we store register match data in. See
regex.texinfo for a full description of what registers match. */
struct re_registers
{
unsigned num_regs;
regoff_t *start;
regoff_t *end;
};
/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
`re_match_2' returns information about at least this many registers
the first time a `regs' structure is passed. */
#ifndef RE_NREGS
# define RE_NREGS 30
#endif
/* POSIX specification for registers. Aside from the different names than
`re_registers', POSIX uses an array of structures, instead of a
structure of arrays. */
typedef struct
{
regoff_t rm_so; /* Byte offset from string's start to substring's start. */
regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
} regmatch_t;
/* Declarations for routines. */
/* To avoid duplicating every routine declaration -- once with a
prototype (if we are ANSI), and once without (if we aren't) -- we
use the following macro to declare argument types. This
unfortunately clutters up the declarations a bit, but I think it's
worth it. */
#if __STDC__
# define _RE_ARGS(args) args
#else /* not __STDC__ */
# define _RE_ARGS(args) ()
#endif /* not __STDC__ */
/* Sets the current default syntax to SYNTAX, and return the old syntax.
You can also simply assign to the `re_syntax_options' variable. */
extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
/* Compile the regular expression PATTERN, with length LENGTH
and syntax given by the global `re_syntax_options', into the buffer
BUFFER. Return NULL if successful, and an error string if not. */
extern const char *re_compile_pattern
_RE_ARGS ((const char *pattern, size_t length,
struct re_pattern_buffer *buffer));
/* Compile a fastmap for the compiled pattern in BUFFER; used to
accelerate searches. Return 0 if successful and -2 if was an
internal error. */
extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
/* Search in the string STRING (with length LENGTH) for the pattern
compiled into BUFFER. Start searching at position START, for RANGE
characters. Return the starting position of the match, -1 for no
match, or -2 for an internal error. Also return register
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
extern int re_search
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
int length, int start, int range, struct re_registers *regs));
/* Like `re_search', but search in the concatenation of STRING1 and
STRING2. Also, stop searching at index START + STOP. */
extern int re_search_2
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
int length1, const char *string2, int length2,
int start, int range, struct re_registers *regs, int stop));
/* Like `re_search', but return how many characters in STRING the regexp
in BUFFER matched, starting at position START. */
extern int re_match
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
int length, int start, struct re_registers *regs));
/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
extern int re_match_2
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
int length1, const char *string2, int length2,
int start, struct re_registers *regs, int stop));
/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
ENDS. Subsequent matches using BUFFER and REGS will use this memory
for recording register information. STARTS and ENDS must be
allocated with malloc, and must each be at least `NUM_REGS * sizeof
(regoff_t)' bytes long.
If NUM_REGS == 0, then subsequent matches should allocate their own
register data.
Unless this function is called, the first search or match using
PATTERN_BUFFER will allocate its own register data, without
freeing the old data. */
extern void re_set_registers
_RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
unsigned num_regs, regoff_t *starts, regoff_t *ends));
#if defined _REGEX_RE_COMP || defined _LIBC
# ifndef _CRAY
/* 4.2 bsd compatibility. */
extern char *re_comp _RE_ARGS ((const char *));
extern int re_exec _RE_ARGS ((const char *));
# endif
#endif
/* POSIX compatibility. */
extern int regcomp _RE_ARGS ((regex_t *__preg, const char *__pattern,
int __cflags));
extern int regexec _RE_ARGS ((const regex_t *__preg,
const char *__string, size_t __nmatch,
regmatch_t __pmatch[], int __eflags));
extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg,
char *__errbuf, size_t __errbuf_size));
extern void regfree _RE_ARGS ((regex_t *__preg));
#ifdef __cplusplus
}
#endif /* C++ */
#endif /* regex.h */
/*
Local variables:
make-backup-files: t
version-control: t
trim-versions-without-asking: nil
End:
*/

270
src/grammar.y Normal file
View File

@ -0,0 +1,270 @@
/* $Id: grammar.y,v 1.23 2003-06-26 18:17:09 rjkaes Exp $
*
* This is the grammar for tinyproxy's configuration file. It needs to be
* in sync with scanner.l. If you know more about yacc and lex than I do
* please update these files.
*
* Copyright (C) 2000 Robert James Kaes (rjkaes@flarenet.com)
*
* 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, 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.
*/
%{
#include "tinyproxy.h"
#include "acl.h"
#include "anonymous.h"
#include "child.h"
#include "filter.h"
#include "htmlerror.h"
#include "log.h"
#include "reqs.h"
void yyerror(char *s);
int yylex(void);
%}
%union {
unsigned int num;
char *cptr;
}
/* statements */
%token KW_PORT KW_LISTEN
%token KW_LOGFILE KW_PIDFILE KW_SYSLOG
%token KW_MAXCLIENTS KW_MAXSPARESERVERS KW_MINSPARESERVERS KW_STARTSERVERS
%token KW_MAXREQUESTSPERCHILD
%token KW_TIMEOUT
%token KW_USER KW_GROUP
%token KW_ANONYMOUS KW_XTINYPROXY
%token KW_FILTER KW_FILTERURLS KW_FILTEREXTENDED KW_FILTER_DEFAULT_DENY
%token KW_FILTER_CASESENSITIVE
%token KW_UPSTREAM
%token KW_CONNECTPORT KW_BIND
%token KW_STATHOST
%token KW_ALLOW KW_DENY
%token KW_ERRORPAGE KW_DEFAULT_ERRORPAGE
%token KW_STATPAGE
%token KW_VIA_PROXY_NAME
/* yes/no switches */
%token KW_YES KW_NO
/* settings for loglevel */
%token KW_LOGLEVEL
%token KW_LOG_CRITICAL KW_LOG_ERROR KW_LOG_WARNING KW_LOG_NOTICE KW_LOG_CONNECT KW_LOG_INFO
%token <cptr> IDENTIFIER
%token <num> NUMBER
%token <cptr> STRING
%token <cptr> NUMERIC_ADDRESS
%token <cptr> NETMASK_ADDRESS
%type <num> yesno
%type <cptr> string
%type <cptr> network_address
%type <cptr> unique_address
%type <num> loglevels
%%
start
: /* empty */
| start line
;
line
: '\n'
| statement '\n'
;
statement
: KW_PORT NUMBER { config.port = $2; }
| KW_TIMEOUT NUMBER { config.idletimeout = $2; }
| KW_SYSLOG yesno
{
#ifdef HAVE_SYSLOG_H
config.syslog = $2;
#else
log_message(LOG_WARNING, "Syslog support was not compiled in.");
#endif
}
| KW_MAXCLIENTS NUMBER { child_configure(CHILD_MAXCLIENTS, $2); }
| KW_MAXSPARESERVERS NUMBER { child_configure(CHILD_MAXSPARESERVERS, $2); }
| KW_MINSPARESERVERS NUMBER { child_configure(CHILD_MINSPARESERVERS, $2); }
| KW_STARTSERVERS NUMBER { child_configure(CHILD_STARTSERVERS, $2); }
| KW_MAXREQUESTSPERCHILD NUMBER { child_configure(CHILD_MAXREQUESTSPERCHILD, $2); }
| KW_LOGFILE string
{
config.logf_name = $2;
if (!config.logf_name) {
fprintf(stderr, "bad log file\n");
}
}
| KW_PIDFILE string { config.pidpath = $2; }
| KW_USER string { config.username = $2; }
| KW_GROUP string { config.group = $2; }
| KW_ANONYMOUS string { anonymous_insert($2); }
| KW_ERRORPAGE NUMBER string { add_new_errorpage($3, $2); }
| KW_DEFAULT_ERRORPAGE string { config.errorpage_undef = $2; }
| KW_STATPAGE string { config.statpage = $2; }
| KW_FILTER string
{
#ifdef FILTER_ENABLE
config.filter = $2;
#else
log_message(LOG_WARNING, "Filter support was not compiled in.");
#endif
}
| KW_FILTERURLS yesno
{
#ifdef FILTER_ENABLE
config.filter_url = $2;
#else
log_message(LOG_WARNING, "Filter support wss not compiled in.");
#endif
}
| KW_FILTEREXTENDED yesno
{
#ifdef FILTER_ENABLE
config.filter_extended = $2;
#else
log_message(LOG_WARNING, "Filter support was not compiled in.");
#endif
}
| KW_FILTER_CASESENSITIVE yesno
{
#ifdef FILTER_ENABLE
config.filter_casesensitive = $2;
#else
log_message(LOG_WARNING, "Filter support was not compiled in.");
#endif
}
| KW_FILTER_DEFAULT_DENY yesno
{
#ifdef FILTER_ENABLE
if ($2)
filter_set_default_policy(FILTER_DEFAULT_DENY);
#else
log_message(LOG_WARNING, "FIlter support was not compiled in.");
#endif
}
| KW_XTINYPROXY network_address
{
#ifdef XTINYPROXY_ENABLE
config.my_domain = $2;
#else
log_message(LOG_WARNING, "X-Tinyproxy header support was not compiled in.");
#endif
}
| KW_UPSTREAM unique_address ':' NUMBER
{
#ifdef UPSTREAM_SUPPORT
upstream_add($2, $4, NULL);
#else
log_message(LOG_WARNING, "Upstream proxy support was not compiled in.");
#endif
}
| KW_UPSTREAM unique_address ':' NUMBER STRING
{
#ifdef UPSTREAM_SUPPORT
upstream_add($2, $4, $5);
#else
log_message(LOG_WARNING, "Upstream proxy support was not compiled in.");
#endif
}
| KW_NO KW_UPSTREAM STRING
{
#ifdef UPSTREAM_SUPPORT
upstream_add(NULL, 0, $3);
#else
log_message(LOG_WARNING, "Upstream proxy support was not compiled in.");
#endif
}
| KW_LISTEN NUMERIC_ADDRESS
{
log_message(LOG_INFO, "Establishing listening socket on IP %s", $2);
config.ipAddr = $2;
}
| KW_ALLOW network_address { insert_acl($2, ACL_ALLOW); }
| KW_DENY network_address { insert_acl($2, ACL_DENY); }
| KW_LOGLEVEL loglevels { set_log_level($2); }
| KW_CONNECTPORT NUMBER { add_connect_port_allowed($2); }
| KW_BIND NUMERIC_ADDRESS
{
#ifndef TRANSPARENT_PROXY
log_message(LOG_INFO, "Binding outgoing connections to %s", $2);
config.bind_address = $2;
#else
log_message(LOG_WARNING, "The 'Bind' directive can not be used with transparent proxy support. Ignoring the directive.");
#endif
}
| KW_VIA_PROXY_NAME string
{
log_message(LOG_INFO, "Setting \"Via\" proxy name to: %s", $2);
config.via_proxy_name = $2;
}
| KW_STATHOST string
{
log_message(LOG_INFO, "Stathost is set to \"%s\"", $2);
config.stathost = $2;
}
;
loglevels
: KW_LOG_CRITICAL { $$ = LOG_CRIT; }
| KW_LOG_ERROR { $$ = LOG_ERR; }
| KW_LOG_WARNING { $$ = LOG_WARNING; }
| KW_LOG_NOTICE { $$ = LOG_NOTICE; }
| KW_LOG_CONNECT { $$ = LOG_CONN; }
| KW_LOG_INFO { $$ = LOG_INFO; }
;
network_address
: unique_address
| NETMASK_ADDRESS
;
unique_address
: IDENTIFIER
| NUMERIC_ADDRESS
;
yesno
: KW_YES { $$ = 1; }
| KW_NO { $$ = 0; }
| NUMBER { $$ = $1; }
;
string
: IDENTIFIER
| STRING
;
%%
extern int yylineno;
void
yyerror(char *s)
{
static int headerdisplayed = 0;
if (!headerdisplayed) {
fprintf(stderr, "Errors in configuration file:\n");
headerdisplayed = 1;
}
fprintf(stderr, "\t%s:%d: %s\n", config.config_file, yylineno, s);
exit(EXIT_FAILURE);
}

508
src/hashmap.c Normal file
View File

@ -0,0 +1,508 @@
/* $Id: hashmap.c,v 1.12 2003-05-31 23:02:21 rjkaes Exp $
*
* A hashmap implementation. The keys are case-insensitive NULL terminated
* strings, and the data is arbitrary lumps of data. Copies of both the
* key and the data in the hashmap itself, so you must free the original
* key and data to avoid a memory leak. The hashmap returns a pointer
* to the data when a key is searched for, so take care in modifying the
* data as it's modifying the data stored in the hashmap. (In other words,
* don't try to free the data, or realloc the memory. :)
*
* Copyright (C) 2002 Robert James Kaes (rjkaes@flarenet.com)
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "tinyproxy.h"
#include "hashmap.h"
#include "heap.h"
/*
* These structures are the storage for the hashmap. Entries are stored in
* struct hashentry_s (the key, data, and length), and all the "buckets" are
* grouped together in hashmap_s. The hashmap_s.size member is for
* internal use. It stores the number of buckets the hashmap was created
* with.
*/
struct hashentry_s {
char *key;
void *data;
size_t len;
struct hashentry_s *prev, *next;
};
struct hashbucket_s {
struct hashentry_s *head, *tail;
};
struct hashmap_s {
unsigned int size;
hashmap_iter end_iterator;
struct hashbucket_s *buckets;
};
/*
* A NULL terminated string is passed to this function and a "hash" value
* is produced within the range of [0 .. size) (In other words, 0 to one
* less than size.)
* The contents of the key are converted to lowercase, so this function
* is not case-sensitive.
*
* If any of the arguments are invalid a negative number is returned.
*/
static int
hashfunc(const char *key, unsigned int size)
{
uint32_t hash;
if (key == NULL)
return -EINVAL;
if (size == 0)
return -ERANGE;
for (hash = tolower(*key++); *key != '\0'; key++) {
uint32_t bit =
(hash & 1) ? (1 << (sizeof(uint32_t) - 1)) : 0;
hash >>= 1;
hash += tolower(*key) + bit;
}
/* Keep the hash within the table limits */
return hash % size;
}
/*
* Create a hashmap with the requested number of buckets. If "nbuckets" is
* not greater than zero a NULL is returned; otherwise, a _token_ to the
* hashmap is returned.
*
* NULLs are also returned if memory could not be allocated for hashmap.
*/
hashmap_t
hashmap_create(unsigned int nbuckets)
{
struct hashmap_s* ptr;
if (nbuckets == 0)
return NULL;
ptr = safecalloc(1, sizeof(struct hashmap_s));
if (!ptr)
return NULL;
ptr->size = nbuckets;
ptr->buckets = safecalloc(nbuckets, sizeof(struct hashbucket_s));
if (!ptr->buckets) {
safefree(ptr);
return NULL;
}
/* This points to "one" past the end of the hashmap. */
ptr->end_iterator = 0;
return ptr;
}
/*
* Follow the chain of hashentries and delete them (including the data and
* the key.)
*
* Returns: 0 if the function completed successfully
* negative number is returned if "entry" was NULL
*/
static inline int
delete_hashbucket(struct hashbucket_s* bucket)
{
struct hashentry_s *nextptr;
struct hashentry_s *ptr;
if (bucket == NULL || bucket->head == NULL)
return -EINVAL;
ptr = bucket->head;
while (ptr) {
nextptr = ptr->next;
safefree(ptr->key);
safefree(ptr->data);
safefree(ptr);
ptr = nextptr;
}
return 0;
}
/*
* Deletes a hashmap. All the key/data pairs are also deleted.
*
* Returns: 0 on success
* negative if a NULL "map" was supplied
*/
int
hashmap_delete(hashmap_t map)
{
unsigned int i;
if (map == NULL)
return -EINVAL;
for (i = 0; i != map->size; i++) {
if (map->buckets[i].head != NULL) {
delete_hashbucket(&map->buckets[i]);
}
}
safefree(map->buckets);
safefree(map);
return 0;
}
/*
* Inserts a NULL terminated string (as the key), plus any arbitrary "data"
* of "len" bytes. Both the key and the data are copied, so the original
* key/data must be freed to avoid a memory leak.
* The "data" must be non-NULL and "len" must be greater than zero. You
* cannot insert NULL data in association with the key.
*
* Returns: 0 on success
* negative number if there are errors
*/
int
hashmap_insert(hashmap_t map, const char *key,
const void *data, size_t len)
{
struct hashentry_s *ptr;
int hash;
char *key_copy;
void *data_copy;
assert(map != NULL);
assert(key != NULL);
assert(data != NULL);
assert(len > 0);
if (map == NULL || key == NULL)
return -EINVAL;
if (!data || len < 1)
return -ERANGE;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
/*
* First make copies of the key and data in case there is a memory
* problem later.
*/
key_copy = safestrdup(key);
if (!key_copy)
return -ENOMEM;
if (data) {
data_copy = safemalloc(len);
if (!data_copy) {
safefree(key_copy);
return -ENOMEM;
}
memcpy(data_copy, data, len);
} else {
data_copy = NULL;
}
ptr = safemalloc(sizeof(struct hashentry_s));
if (!ptr) {
safefree(key_copy);
safefree(data_copy);
return -ENOMEM;
}
ptr->key = key_copy;
ptr->data = data_copy;
ptr->len = len;
/*
* Now add the entry to the end of the bucket chain.
*/
ptr->next = NULL;
ptr->prev = map->buckets[hash].tail;
if (map->buckets[hash].tail)
map->buckets[hash].tail->next = ptr;
map->buckets[hash].tail = ptr;
if (!map->buckets[hash].head)
map->buckets[hash].head = ptr;
map->end_iterator++;
return 0;
}
/*
* Get an iterator to the first entry.
*
* Returns: an negative value upon error.
*/
hashmap_iter
hashmap_first(hashmap_t map)
{
assert(map != NULL);
if (!map)
return -EINVAL;
if (map->end_iterator == 0)
return -1;
else
return 0;
}
/*
* Checks to see if the iterator is pointing at the "end" of the entries.
*
* Returns: 1 if it is the end
* 0 otherwise
*/
int
hashmap_is_end(hashmap_t map, hashmap_iter iter)
{
assert(map != NULL);
assert(iter >= 0);
if (!map || iter < 0)
return -EINVAL;
if (iter == map->end_iterator)
return 1;
else
return 0;
}
/*
* Return a "pointer" to the first instance of the particular key. It can
* be tested against hashmap_is_end() to see if the key was not found.
*
* Returns: negative upon an error
* an "iterator" pointing at the first key
* an "end-iterator" if the key wasn't found
*/
hashmap_iter
hashmap_find(hashmap_t map, const char* key)
{
unsigned int i;
hashmap_iter iter = 0;
struct hashentry_s* ptr;
assert(map != NULL);
assert(key != NULL);
if (!map || !key)
return -EINVAL;
/*
* Loop through all the keys and look for the first occurrence
* of a particular key.
*/
for (i = 0; i != map->size; i++) {
ptr = map->buckets[i].head;
while (ptr) {
if (strcasecmp(ptr->key, key) == 0) {
/* Found it, so return the current count */
return iter;
}
iter++;
ptr = ptr->next;
}
}
return iter;
}
/*
* Retrieve the data associated with a particular iterator.
*
* Returns: the length of the data block upon success
* negative upon error
*/
ssize_t
hashmap_return_entry(hashmap_t map, hashmap_iter iter,
char** key, void** data)
{
unsigned int i;
struct hashentry_s* ptr;
hashmap_iter count = 0;
assert(map != NULL);
assert(iter >= 0);
assert(iter != map->end_iterator);
assert(key != NULL);
assert(data != NULL);
if (!map || iter < 0 || !key || !data)
return -EINVAL;
for (i = 0; i != map->size; i++) {
ptr = map->buckets[i].head;
while (ptr) {
if (count == iter) {
/* This is the data so return it */
*key = ptr->key;
*data = ptr->data;
return ptr->len;
}
ptr = ptr->next;
count++;
}
}
return -EFAULT;
}
/*
* Searches for _any_ occurrences of "key" within the hashmap.
*
* Returns: negative upon an error
* zero if no key is found
* count found
*/
ssize_t
hashmap_search(hashmap_t map, const char *key)
{
int hash;
struct hashentry_s* ptr;
ssize_t count = 0;
if (map == NULL || key == NULL)
return -EINVAL;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
ptr = map->buckets[hash].head;
/* All right, there is an entry here, now see if it's the one we want */
while (ptr) {
if (strcasecmp(ptr->key, key) == 0)
++count;
/* This entry didn't contain the key; move to the next one */
ptr = ptr->next;
}
return count;
}
/*
* Get the first entry (assuming there is more than one) for a particular
* key. The data MUST be non-NULL.
*
* Returns: negative upon error
* zero if no entry is found
* length of data for the entry
*/
ssize_t
hashmap_entry_by_key(hashmap_t map, const char* key, void** data)
{
int hash;
struct hashentry_s* ptr;
if (!map || !key || !data)
return -EINVAL;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
ptr = map->buckets[hash].head;
while (ptr) {
if (strcasecmp(ptr->key, key) == 0) {
*data = ptr->data;
return ptr->len;
}
ptr = ptr->next;
}
return 0;
}
/*
* Go through the hashmap and remove the particular key.
* NOTE: This will invalidate any iterators which have been created.
*
* Remove: negative upon error
* 0 if the key was not found
* positive count of entries deleted
*/
ssize_t
hashmap_remove(hashmap_t map, const char *key)
{
int hash;
struct hashentry_s *ptr, *next;
short int deleted = 0;
if (map == NULL || key == NULL)
return -EINVAL;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
ptr = map->buckets[hash].head;
while (ptr) {
if (strcasecmp(ptr->key, key) == 0) {
/*
* Found the data, now need to remove everything
* and update the hashmap.
*/
next = ptr->next;
if (ptr->prev)
ptr->prev->next = ptr->next;
if (ptr->next)
ptr->next->prev = ptr->prev;
if (map->buckets[hash].head == ptr)
map->buckets[hash].head = ptr->next;
if (map->buckets[hash].tail == ptr)
map->buckets[hash].tail = ptr->prev;
safefree(ptr->key);
safefree(ptr->data);
safefree(ptr);
++deleted;
--map->end_iterator;
ptr = next;
continue;
}
/* This entry didn't contain the key; move to the next one */
ptr = ptr->next;
}
/* The key was not found, so return 0 */
return deleted;
}

133
src/hashmap.h Normal file
View File

@ -0,0 +1,133 @@
/* $Id: hashmap.h,v 1.2 2002-04-25 18:55:56 rjkaes Exp $
*
* A hashmap implementation. The keys are case-insensitive NULL terminated
* strings, and the data is arbitrary lumps of data. Copies of both the
* key and the data in the hashmap itself, so you must free the original
* key and data to avoid a memory leak. The hashmap returns a pointer
* to the data when a key is searched for, so take care in modifying the
* data as it's modifying the data stored in the hashmap. (In other words,
* don't try to free the data, or realloc the memory. :)
*
* Copyright (C) 2002 Robert James Kaes (rjkaes@flarenet.com)
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _HASHMAP_H
#define _HASHMAP_H
/* Allow the use in C++ code. */
#if defined(__cplusplus)
extern "C" {
#endif
/*
* We're using a typedef here to "hide" the implementation details of the
* hash map. Sure, it's a pointer, but the struct is hidden in the C file.
* So, just use the hashmap_t like it's a cookie. :)
*/
typedef struct hashmap_s* hashmap_t;
typedef int hashmap_iter;
/*
* hashmap_create() takes one argument, which is the number of buckets to
* use internally. hashmap_delete() is self explanatory.
*/
extern hashmap_t hashmap_create(unsigned int nbuckets);
extern int hashmap_delete(hashmap_t map);
/*
* When the you insert a key/data pair into the hashmap it will the key
* and data are duplicated, so you must free your copy if it was created
* on the heap. The key must be a NULL terminated string. "data" must be
* non-NULL and length must be greater than zero.
*
* Returns: negative on error
* 0 upon successful insert
*/
extern int hashmap_insert(hashmap_t map, const char *key,
const void *data, size_t len);
/*
* Get an iterator to the first entry.
*
* Returns: an negative value upon error.
*/
extern hashmap_iter hashmap_first(hashmap_t map);
/*
* Checks to see if the iterator is pointing at the "end" of the entries.
*
* Returns: 1 if it is the end
* 0 otherwise
*/
extern int hashmap_is_end(hashmap_t map, hashmap_iter iter);
/*
* Return a "pointer" to the first instance of the particular key. It can
* be tested against hashmap_is_end() to see if the key was not found.
*
* Returns: negative upon an error
* an "iterator" pointing at the first key
* an "end-iterator" if the key wasn't found
*/
extern hashmap_iter hashmap_find(hashmap_t map, const char* key);
/*
* Retrieve the key/data associated with a particular iterator.
* NOTE: These are pointers to the actual data, so don't mess around with them
* too much.
*
* Returns: the length of the data block upon success
* negative upon error
*/
extern ssize_t hashmap_return_entry(hashmap_t map, hashmap_iter iter,
char** key, void** data);
/*
* Get the first entry (assuming there is more than one) for a particular
* key. The data MUST be non-NULL.
*
* Returns: negative upon error
* zero if no entry is found
* length of data for the entry
*/
extern ssize_t hashmap_entry_by_key(hashmap_t map, const char* key, void** data);
/*
* Searches for _any_ occurrances of "key" within the hashmap and returns the
* number of matching entries.
*
* Returns: negative upon an error
* zero if no key is found
* count found (positive value)
*/
extern ssize_t hashmap_search(hashmap_t map, const char *key);
/*
* Go through the hashmap and remove the particular key.
* NOTE: This will invalidate any iterators which have been created.
*
* Remove: negative upon error
* 0 if the key was not found
* positive count of entries deleted
*/
extern ssize_t hashmap_remove(hashmap_t map, const char *key);
#if defined(__cplusplus)
}
#endif /* C++ */
#endif /* _HASHMAP_H */

View File

@ -1,99 +1,156 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2002 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: heap.c,v 1.6.2.1 2003-08-06 20:44:09 rjkaes Exp $
*
* 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.
*/
/* Debugging versions of various heap related functions are combined
* Debugging versions of various heap related functions are combined
* here. The debugging versions include assertions and also print
* (to standard error) the function called along with the amount
* of memory allocated, and where the memory is pointing. The
* format of the log message is standardized.
*
* Copyright (C) 2002 Robert James Kaes (rjkaes@flarenet.com)
*
* 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, 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.
*/
#include "main.h"
#include "tinyproxy.h"
#include "heap.h"
#include "text.h"
#ifndef NDEBUG
void *debugging_calloc (size_t nmemb, size_t size, const char *file,
unsigned long line)
void *
debugging_calloc(size_t nmemb, size_t size, const char *file,
unsigned long line)
{
void *ptr;
void *ptr;
assert (nmemb > 0);
assert (size > 0);
assert(nmemb > 0);
assert(size > 0);
ptr = calloc (nmemb, size);
fprintf (stderr, "{calloc: %p:%lu x %lu} %s:%lu\n", ptr,
(unsigned long) nmemb, (unsigned long) size, file, line);
return ptr;
ptr = calloc(nmemb, size);
fprintf(stderr, "{calloc: %p:%zu x %zu} %s:%lu\n",
ptr, nmemb, size, file, line);
return ptr;
}
void *debugging_malloc (size_t size, const char *file, unsigned long line)
void *
debugging_malloc(size_t size, const char *file, unsigned long line)
{
void *ptr;
void *ptr;
assert (size > 0);
assert(size > 0);
ptr = malloc (size);
fprintf (stderr, "{malloc: %p:%lu} %s:%lu\n", ptr,
(unsigned long) size, file, line);
return ptr;
ptr = malloc(size);
fprintf(stderr, "{malloc: %p:%zu} %s:%lu\n",
ptr, size, file, line);
return ptr;
}
void *debugging_realloc (void *ptr, size_t size, const char *file,
unsigned long line)
void *
debugging_realloc(void *ptr, size_t size, const char *file, unsigned long line)
{
void *newptr;
void *newptr;
assert (size > 0);
assert(size > 0);
newptr = realloc (ptr, size);
fprintf (stderr, "{realloc: %p -> %p:%lu} %s:%lu\n", ptr, newptr,
(unsigned long) size, file, line);
return newptr;
newptr = realloc(ptr, size);
fprintf(stderr, "{realloc: %p -> %p:%zu} %s:%lu\n",
ptr, newptr, size, file, line);
return newptr;
}
void debugging_free (void *ptr, const char *file, unsigned long line)
void
debugging_free(void *ptr, const char *file, unsigned long line)
{
fprintf (stderr, "{free: %p} %s:%lu\n", ptr, file, line);
fprintf(stderr, "{free: %p} %s:%lu\n", ptr, file, line);
if (ptr != NULL)
free (ptr);
return;
if (ptr != NULL)
free(ptr);
return;
}
char *debugging_strdup (const char *s, const char *file, unsigned long line)
char*
debugging_strdup(const char *s, const char *file, unsigned long line)
{
char *ptr;
size_t len;
char* ptr;
size_t len;
assert (s != NULL);
assert(s != NULL);
len = strlen (s) + 1;
ptr = (char *) malloc (len);
if (!ptr)
return NULL;
memcpy (ptr, s, len);
len = strlen(s) + 1;
ptr = malloc(len);
if (!ptr)
return NULL;
memcpy(ptr, s, len);
fprintf (stderr, "{strdup: %p:%lu} %s:%lu\n", ptr,
(unsigned long) len, file, line);
return ptr;
fprintf(stderr, "{strdup: %p:%zu} %s:%lu\n",
ptr, len, file, line);
return ptr;
}
#endif /* !NDEBUG */
/*
* Allocate a block of memory in the "shared" memory region.
*
* FIXME: This uses the most basic (and slowest) means of creating a
* shared memory location. It requires the use of a temporary file. We might
* want to look into something like MM (Shared Memory Library) for a better
* solution.
*/
void*
malloc_shared_memory(size_t size)
{
int fd;
void* ptr;
char buffer[32];
static char* shared_file = "/tmp/tinyproxy.shared.XXXXXX";
assert(size > 0);
strlcpy(buffer, shared_file, sizeof(buffer));
/* Only allow u+rw bits. This may be required for some versions
* of glibc so that mkstemp() doesn't make us vulnerable.
*/
umask(0177);
if ((fd = mkstemp(buffer)) == -1)
return (void *)MAP_FAILED;
unlink(buffer);
if (ftruncate(fd, size) == -1)
return (void *)MAP_FAILED;
ptr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
return ptr;
}
/*
* Allocate a block of memory from the "shared" region an initialize it to
* zero.
*/
void*
calloc_shared_memory(size_t nmemb, size_t size)
{
void* ptr;
long length;
assert(nmemb > 0);
assert(size > 0);
length = nmemb * size;
ptr = malloc_shared_memory(length);
if (ptr == MAP_FAILED)
return ptr;
memset(ptr, 0, length);
return ptr;
}

View File

@ -1,23 +1,20 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2002 Robert James Kaes <rjkaes@users.sourceforge.net>
/* $Id: heap.h,v 1.3 2003-05-31 23:04:15 rjkaes Exp $
*
* 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.
* See 'heap.c' for a detailed description.
*
* 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.
* Copyright (C) 2002 Robert James Kaes (rjkaes@flarenet.com)
*
* 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.
* 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, 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.
*/
/* See 'heap.c' for detailed information. */
#ifndef TINYPROXY_HEAP_H
#define TINYPROXY_HEAP_H
@ -26,15 +23,15 @@
*/
#ifndef NDEBUG
extern void *debugging_calloc (size_t nmemb, size_t size, const char *file,
unsigned long line);
extern void *debugging_malloc (size_t size, const char *file,
unsigned long line);
extern void debugging_free (void *ptr, const char *file, unsigned long line);
extern void *debugging_realloc (void *ptr, size_t size, const char *file,
unsigned long line);
extern char *debugging_strdup (const char *s, const char *file,
unsigned long line);
extern void *debugging_calloc(size_t nmemb, size_t size, const char *file,
unsigned long line);
extern void *debugging_malloc(size_t size, const char *file,
unsigned long line);
extern void debugging_free(void *ptr, const char *file, unsigned long line);
extern void *debugging_realloc(void *ptr, size_t size, const char *file,
unsigned long line);
extern char *debugging_strdup(const char* s, const char* file,
unsigned long line);
# define safecalloc(x, y) debugging_calloc(x, y, __FILE__, __LINE__)
# define safemalloc(x) debugging_malloc(x, __FILE__, __LINE__)
@ -52,4 +49,10 @@ extern char *debugging_strdup (const char *s, const char *file,
#endif
/*
* Allocate memory from the "shared" region of memory.
*/
extern void* malloc_shared_memory(size_t size);
extern void* calloc_shared_memory(size_t nmemb, size_t size);
#endif

View File

@ -1,179 +0,0 @@
#include "common.h"
#include "hostspec.h"
#include "heap.h"
#include "network.h"
static int dotted_mask(char *bitmask_string, unsigned char array[])
{
unsigned char v4bits[4];
if (1 != inet_pton (AF_INET, bitmask_string, v4bits)) return -1;
memset (array, 0xff, IPV6_LEN-4);
memcpy (array + IPV6_LEN-4, v4bits, 4);
return 0;
}
/*
* Fills in the netmask array given a numeric value.
*
* Returns:
* 0 on success
* -1 on failure (invalid mask value)
*
*/
static int
fill_netmask_array (char *bitmask_string, int v6,
unsigned char array[])
{
unsigned int i;
unsigned long int mask;
char *endptr;
errno = 0; /* to distinguish success/failure after call */
if (strchr (bitmask_string, '.')) {
if (v6) return -1; /* ipv6 doesn't supported dotted netmasks */
return dotted_mask(bitmask_string, array);
}
mask = strtoul (bitmask_string, &endptr, 10);
/* check for various conversion errors */
if ((errno == ERANGE && mask == ULONG_MAX)
|| (errno != 0 && mask == 0) || (endptr == bitmask_string))
return -1;
if (v6 == 0) {
/* The mask comparison is done as an IPv6 address, so
* convert to a longer mask in the case of IPv4
* addresses. */
mask += 12 * 8;
}
/* check valid range for a bit mask */
if (mask > (8 * IPV6_LEN))
return -1;
/* we have a valid range to fill in the array */
for (i = 0; i != IPV6_LEN; ++i) {
if (mask >= 8) {
array[i] = 0xff;
mask -= 8;
} else if (mask > 0) {
array[i] = (unsigned char) (0xff << (8 - mask));
mask = 0;
} else {
array[i] = 0;
}
}
return 0;
}
/* parse a location string containing either an ipv4/ipv4 + hostmask tuple
or a dnsname into a struct hostspec.
returns 0 on success, non-0 on error (might be memory allocation, bogus
ip address or mask).
*/
int hostspec_parse(char *location, struct hostspec *h) {
char *mask, ip_dst[IPV6_LEN];
h->type = HST_NONE;
if(!location) return 0;
memset(h, 0, sizeof(*h));
if ((mask = strrchr(location, '/')))
*(mask++) = 0;
/*
* Check for a valid IP address (the simplest case) first.
*/
if (full_inet_pton (location, ip_dst) > 0) {
h->type = HST_NUMERIC;
memcpy (h->address.ip.network, ip_dst, IPV6_LEN);
if(!mask) memset (h->address.ip.mask, 0xff, IPV6_LEN);
else {
char dst[sizeof(struct in6_addr)];
int v6, i;
/* Check if the IP address before the netmask is
* an IPv6 address */
if (inet_pton(AF_INET6, location, dst) > 0)
v6 = 1;
else
v6 = 0;
if (fill_netmask_array
(mask, v6, &(h->address.ip.mask[0]))
< 0)
goto err;
for (i = 0; i < IPV6_LEN; i++)
h->address.ip.network[i] = ip_dst[i] &
h->address.ip.mask[i];
}
} else {
/* either bogus IP or hostname */
/* bogus ipv6 ? */
if (mask || strchr (location, ':'))
goto err;
/* In all likelihood a string */
h->type = HST_STRING;
h->address.string = safestrdup (location);
if (!h->address.string)
goto err;
}
/* restore mask */
if(mask) *(--mask) = '/';
return 0;
err:;
if(mask) *(--mask) = '/';
return -1;
}
static int string_match(const char *ip, const char *addrspec)
{
size_t test_length, match_length;
if(!strcasecmp(ip, addrspec)) return 1;
if(addrspec[0] != '.') return 0;
test_length = strlen (ip);
match_length = strlen (addrspec);
if (test_length < match_length) return 0;
return (strcasecmp
(ip + (test_length - match_length),
addrspec) == 0);
}
static int numeric_match(const uint8_t addr[], const struct hostspec *h)
{
uint8_t x, y;
int i;
for (i = 0; i != IPV6_LEN; ++i) {
x = addr[i] & h->address.ip.mask[i];
y = h->address.ip.network[i];
/* If x and y don't match, the IP addresses don't match */
if (x != y)
return 0;
}
return 1;
}
/* check whether ip matches hostspec.
return 1 on match, 0 on non-match */
int hostspec_match(const char *ip, const struct hostspec *h) {
int is_numeric_addr;
uint8_t numeric_addr[IPV6_LEN];
if (ip[0] == '\0') return 0;
is_numeric_addr = (full_inet_pton (ip, &numeric_addr) > 0);
switch (h->type) {
case HST_STRING:
if(is_numeric_addr) return 0;
return string_match (ip, h->address.string);
case HST_NUMERIC:
return numeric_match (numeric_addr, h);
case HST_NONE:
return 0;
}
return 0;
}

View File

@ -1,26 +0,0 @@
#ifndef HOSTSPEC_H
#define HOSTSPEC_H
#define IPV6_LEN 16
enum hostspec_type {
HST_NONE,
HST_STRING,
HST_NUMERIC,
};
struct hostspec {
enum hostspec_type type;
union {
char *string;
struct {
unsigned char network[IPV6_LEN];
unsigned char mask[IPV6_LEN];
} ip;
} address;
};
int hostspec_parse(char *domain, struct hostspec *h);
int hostspec_match(const char *ip, const struct hostspec *h);
#endif

View File

@ -1,222 +0,0 @@
/*
musl license, hsearch.c originally written by Szabolcs Nagy
Copyright © 2005-2020 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include "hsearch.h"
/*
open addressing hash table with 2^n table size
quadratic probing is used in case of hash collision
tab indices and hash are size_t
after resize fails with ENOMEM the state of tab is still usable
*/
typedef struct htab_entry {
char *key;
htab_value data;
} htab_entry;
struct elem {
htab_entry item;
size_t hash;
};
struct htab {
struct elem *elems;
size_t mask;
size_t used;
size_t seed;
size_t dead;
};
#define MINSIZE 8
#define MAXSIZE ((size_t)-1/2 + 1)
#define CASE_INSENSITIVE
#ifdef CASE_INSENSITIVE
#include <ctype.h>
#include <strings.h>
#define LOWER_OR_NOT(X) tolower(X)
#define STRCMP(X, Y) strcasecmp(X, Y)
#else
#define LOWER_OR_NOT(X) X
#define STRCMP(X, Y) strcmp(X, Y)
#endif
static size_t keyhash(const char *k, size_t seed)
{
const unsigned char *p = (const void *)k;
size_t h = seed;
while (*p)
h = 31*h + LOWER_OR_NOT(*p++);
return h;
}
static int resize(struct htab *htab, size_t nel)
{
size_t newsize;
size_t i, j;
size_t oldmask = htab->mask;
struct elem *e, *newe;
struct elem *oldtab = htab->elems;
struct elem *oldend;
if (nel > MAXSIZE)
nel = MAXSIZE;
for (newsize = MINSIZE; newsize < nel; newsize *= 2);
htab->elems = calloc(newsize, sizeof *htab->elems);
if (!htab->elems) {
htab->elems = oldtab;
return 0;
}
htab->mask = newsize - 1;
if (!oldtab)
return 1;
oldend = oldtab + oldmask + 1;
for (e = oldtab; e < oldend; e++)
if (e->item.key) {
for (i=e->hash,j=1; ; i+=j++) {
newe = htab->elems + (i & htab->mask);
if (!newe->item.key)
break;
}
*newe = *e;
}
free(oldtab);
return 1;
}
static struct elem *lookup(struct htab *htab, const char *key, size_t hash, size_t dead)
{
size_t i, j;
struct elem *e;
for (i=hash,j=1; ; i+=j++) {
e = htab->elems + (i & htab->mask);
if ((!e->item.key && (!e->hash || e->hash == dead)) ||
(e->hash==hash && STRCMP(e->item.key, key)==0))
break;
}
return e;
}
struct htab *htab_create(size_t nel)
{
struct htab *r = calloc(1, sizeof *r);
if(r && !resize(r, nel)) {
free(r);
r = 0;
}
r->seed = rand();
return r;
}
void htab_destroy(struct htab *htab)
{
free(htab->elems);
free(htab);
}
static struct elem *htab_find_elem(struct htab *htab, const char* key)
{
size_t hash = keyhash(key, htab->seed);
struct elem *e = lookup(htab, key, hash, 0);
if (e->item.key) {
return e;
}
return 0;
}
htab_value* htab_find(struct htab *htab, const char* key)
{
struct elem *e = htab_find_elem(htab, key);
if(!e) return 0;
return &e->item.data;
}
htab_value* htab_find2(struct htab *htab, const char* key, char **saved_key)
{
struct elem *e = htab_find_elem(htab, key);
if(!e) return 0;
*saved_key = e->item.key;
return &e->item.data;
}
int htab_delete(struct htab *htab, const char* key)
{
struct elem *e = htab_find_elem(htab, key);
if(!e) return 0;
e->item.key = 0;
e->hash = 0xdeadc0de;
--htab->used;
++htab->dead;
return 1;
}
int htab_insert(struct htab *htab, char* key, htab_value value)
{
size_t hash = keyhash(key, htab->seed), oh;
struct elem *e = lookup(htab, key, hash, 0xdeadc0de);
if(e->item.key) {
/* it's not allowed to overwrite existing data */
return 0;
}
oh = e->hash; /* save old hash in case it's tombstone marker */
e->item.key = key;
e->item.data = value;
e->hash = hash;
if (++htab->used + htab->dead > htab->mask - htab->mask/4) {
if (!resize(htab, 2*htab->used)) {
htab->used--;
e->item.key = 0;
e->hash = oh;
return 0;
}
htab->dead = 0;
} else if (oh == 0xdeadc0de) {
/* re-used tomb */
--htab->dead;
}
return 1;
}
size_t htab_next(struct htab *htab, size_t iterator, char** key, htab_value **v)
{
size_t i;
for(i=iterator;i<htab->mask+1;++i) {
struct elem *e = htab->elems + i;
if(e->item.key) {
*key = e->item.key;
*v = &e->item.data;
return i+1;
}
}
return 0;
}

View File

@ -1,23 +0,0 @@
#ifndef HSEARCH_H
#define HSEARCH_H
#include <stdlib.h>
typedef union htab_value {
void *p;
size_t n;
} htab_value;
#define HTV_N(N) (htab_value) {.n = N}
#define HTV_P(P) (htab_value) {.p = P}
struct htab * htab_create(size_t);
void htab_destroy(struct htab *);
htab_value* htab_find(struct htab *, const char* key);
/* same as htab_find, but can retrieve the saved key (for freeing) */
htab_value* htab_find2(struct htab *htab, const char* key, char **saved_key);
int htab_insert(struct htab *, char*, htab_value);
int htab_delete(struct htab *htab, const char* key);
size_t htab_next(struct htab *, size_t iterator, char** key, htab_value **v);
#endif

View File

@ -1,320 +0,0 @@
/* tinyproxy - A fast light-weight HTTP proxy
* Copyright (C) 2003 Steven Young <sdyoung@miranda.org>
*
* 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.
*/
/* This file contains source code for the handling and display of
* HTML error pages with variable substitution.
*/
#include "common.h"
#include "main.h"
#include "buffer.h"
#include "conns.h"
#include "heap.h"
#include "html-error.h"
#include "network.h"
#include "utils.h"
#include "conf.h"
#include "log.h"
#include <regex.h>
/*
* Add an error number -> filename mapping to the errorpages list.
*/
#define ERRORNUM_BUFSIZE 8 /* this is more than required */
#define ERRPAGES_BUCKETCOUNT 16
int add_new_errorpage (struct config_s *conf, char *filepath,
unsigned int errornum)
{
char errornbuf[ERRORNUM_BUFSIZE], *k;
if (!conf->errorpages)
conf->errorpages = htab_create (ERRPAGES_BUCKETCOUNT);
if (!conf->errorpages)
return (-1);
snprintf (errornbuf, ERRORNUM_BUFSIZE, "%u", errornum);
k = safestrdup(errornbuf);
if (!k) return -1;
if (!htab_insert (conf->errorpages, k, HTV_P(filepath))) {
safefree(k);
return (-1);
}
return (0);
}
/*
* Get the file appropriate for a given error.
*/
static char *get_html_file (unsigned int errornum)
{
char errornbuf[ERRORNUM_BUFSIZE];
htab_value *hv;
assert (errornum >= 100 && errornum < 1000);
if (!config->errorpages)
return (config->errorpage_undef);
snprintf (errornbuf, ERRORNUM_BUFSIZE, "%u", errornum);
hv = htab_find (config->errorpages, errornbuf);
if (!hv) return (config->errorpage_undef);
return hv->p;
}
static char *lookup_variable (struct htab *map, const char *varname) {
htab_value *v;
v = htab_find(map, varname);
return v ? v->p : 0;
}
static void varsubst_sendline(struct conn_s *connptr, regex_t *re, char *p) {
int fd = connptr->client_fd;
while(*p) {
regmatch_t match;
char varname[32+1], *varval;
size_t l;
int st = regexec(re, p, 1, &match, 0);
if(st == 0) {
if(match.rm_so > 0) safe_write(fd, p, match.rm_so);
l = match.rm_eo - match.rm_so;
assert(l>2 && l-2 < sizeof(varname));
p += match.rm_so;
memcpy(varname, p+1, l-2);
varname[l-2] = 0;
varval = lookup_variable(connptr->error_variables, varname);
if(varval) write_message(fd, "%s", varval);
else if(varval && !*varval) write_message(fd, "(unknown)");
else safe_write(fd, p, l);
p += l;
} else {
write_message(fd, "%s", p);
break;
}
}
}
/*
* Send an already-opened file to the client with variable substitution.
*/
int
send_html_file (FILE *infile, struct conn_s *connptr)
{
regex_t re;
char *inbuf = safemalloc (4096);
(void) regcomp(&re, "{[a-z]\\{1,32\\}}", 0);
while (fgets (inbuf, 4096, infile)) {
varsubst_sendline(connptr, &re, inbuf);
}
regfree (&re);
safefree (inbuf);
return 1;
}
int send_http_headers (
struct conn_s *connptr, int code,
const char *message, const char *extra)
{
const char headers[] =
"HTTP/1.%u %d %s\r\n"
"Server: %s\r\n"
"Content-Type: text/html\r\n"
"%s"
"Connection: close\r\n" "\r\n";
return (write_message (connptr->client_fd, headers,
connptr->protocol.major != 1 ? 0 : connptr->protocol.minor,
code, message, PACKAGE,
extra));
}
/*
* Display an error to the client.
*/
int send_http_error_message (struct conn_s *connptr)
{
char *error_file;
FILE *infile;
int ret;
const char *fallback_error =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" "
"\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
"<html>\n"
"<head><title>%d %s</title></head>\n"
"<body>\n"
"<h1>%s</h1>\n"
"<p>%s</p>\n"
"<hr />\n"
"<p><em>Generated by %s.</em></p>\n" "</body>\n"
"</html>\n";
/* according to rfc7235, the 407 error must be accompanied by
a Proxy-Authenticate header field. */
const char *auth_str_type =
connptr->error_number == 407 ? "Proxy-Authenticate" :
(connptr->error_number == 401 ? "WWW-Authenticate" : "");
const char auth_str_tpl[] = "%s: Basic realm=\"%s\"\r\n";
char* auth_str_add = NULL;
if (auth_str_type[0] != 0) {
int auth_str_size = snprintf (NULL, 0, auth_str_tpl,
auth_str_type, config->basicauth_realm) + 1;
if (auth_str_size > 0) {
auth_str_add = safemalloc (auth_str_size);
if (auth_str_add != NULL) {
snprintf (auth_str_add, auth_str_size, auth_str_tpl,
auth_str_type, config->basicauth_realm);
}
}
}
send_http_headers (connptr, connptr->error_number,
connptr->error_string, auth_str_add ? auth_str_add : "");
if (auth_str_add) safefree (auth_str_add);
error_file = get_html_file (connptr->error_number);
if (!error_file || !(infile = fopen (error_file, "r"))) {
char *detail;
if (error_file) log_message (LOG_ERR,
"Error opening error file '%s' (%s)",
error_file, strerror (errno));
detail = lookup_variable (connptr->error_variables, "detail");
return (write_message (connptr->client_fd, fallback_error,
connptr->error_number,
connptr->error_string,
connptr->error_string,
detail, PACKAGE));
}
ret = send_html_file (infile, connptr);
fclose (infile);
return (ret);
}
/*
* Add a key -> value mapping for HTML file substitution.
*/
#define ERRVAR_BUCKETCOUNT 16
int
add_error_variable (struct conn_s *connptr, const char *key, const char *val)
{
char *k, *v;
if (!connptr->error_variables)
if (!
(connptr->error_variables =
htab_create (ERRVAR_BUCKETCOUNT)))
return (-1);
k = safestrdup(key);
v = safestrdup(val);
if (!v || !k) goto oom;
if(htab_insert (connptr->error_variables, k, HTV_P(v)))
return 1;
oom:;
safefree(k);
safefree(v);
return -1;
}
#define ADD_VAR_RET(x, y) \
do { \
if (y == NULL) \
break; \
if (add_error_variable(connptr, x, y) < 0) \
return -1; \
} while (0)
/*
* Set some standard variables used by all HTML pages
*/
int add_standard_vars (struct conn_s *connptr)
{
char errnobuf[16];
char timebuf[30];
time_t global_time;
struct tm tm_buf;
snprintf (errnobuf, sizeof errnobuf, "%d", connptr->error_number);
ADD_VAR_RET ("errno", errnobuf);
ADD_VAR_RET ("cause", connptr->error_string);
ADD_VAR_RET ("request", connptr->request_line);
ADD_VAR_RET ("clientip", connptr->client_ip_addr);
/* The following value parts are all non-NULL and will
* trigger warnings in ADD_VAR_RET(), so we use
* add_error_variable() directly.
*/
global_time = time (NULL);
strftime (timebuf, sizeof (timebuf), "%a, %d %b %Y %H:%M:%S GMT",
gmtime_r (&global_time, &tm_buf));
add_error_variable (connptr, "date", timebuf);
add_error_variable (connptr, "website",
"https://tinyproxy.github.io/");
add_error_variable (connptr, "version", VERSION);
add_error_variable (connptr, "package", PACKAGE);
return (0);
}
/*
* Add the error information to the conn structure.
*/
int
indicate_http_error (struct conn_s *connptr, int number,
const char *message, ...)
{
va_list ap;
char *key, *val;
va_start (ap, message);
while ((key = va_arg (ap, char *))) {
val = va_arg (ap, char *);
if (add_error_variable (connptr, key, val) == -1) {
va_end (ap);
return (-1);
}
}
connptr->error_number = number;
connptr->error_string = safestrdup (message);
va_end (ap);
return (add_standard_vars (connptr));
}

Some files were not shown because too many files have changed in this diff Show More