Commit ee35841b authored by Toby Dickenson's avatar Toby Dickenson

Implemented smarter-than-REMOTE_ADDR proposal. IP-based access controls now work through a proxy.

parent d4803f24
......@@ -12,6 +12,13 @@ Zope Changes
objects to allow gathering of permission names for products like
DocFinder and VerboseSecurity.
- Added a new REQUEST method, getClientAddr(), to determine a clients
IP address. Address restrictions in the user folder have been changed
to use this method. By default the value returned by this method is the
same as the initial value of REQUEST['REMOTE_ADDR']. Zope also has
support for obtaining a more useful value from other headers if a
front-end proxy is in use. See doc/ENVIRONMENT.txt for details.
Bugs Fixed
- The ZEO unit tests and wo_pcgi.py didn't run on Windows if the path
......
......@@ -78,6 +78,15 @@ SiteAccess
If set, all site access rules are suppressed (used by SiteAccess
products).
ZPublisher
ZOPE_TRUSTED_PROXIES
A colon seperated list of IP addresses which run trusted
proxy servers. If a connection comes from an address listed
here, Zope will trust any X-Forwarded-For header to contain
the users real IP address for the purposes of address-based
authentication limits.
ZEO
......
......@@ -12,7 +12,7 @@
##############################################################################
"""Access control package"""
__version__='$Revision: 1.174 $'[11:-2]
__version__='$Revision: 1.175 $'[11:-2]
import Globals, socket, SpecialUsers,re
import os
......@@ -1113,8 +1113,7 @@ def domainSpecMatch(spec, request):
if request.has_key('REMOTE_HOST'):
host=request['REMOTE_HOST']
if request.has_key('REMOTE_ADDR'):
addr=request['REMOTE_ADDR']
addr=request.getClientAddr()
if not host and not addr:
return 0
......
......@@ -11,7 +11,7 @@
#
##############################################################################
__version__='$Revision: 1.86 $'[11:-2]
__version__='$Revision: 1.87 $'[11:-2]
import re, sys, os, urllib, time, random, cgi, codecs
from types import StringType, UnicodeType
......@@ -223,6 +223,11 @@ class HTTPRequest(BaseRequest):
del self.other[x]
self._urls = ()
def getClientAddr(self):
""" The IP address of the client.
"""
return self._client_addr
def __init__(self, stdin, environ, response, clean=0):
self._orig_env=environ
# Avoid the overhead of scrubbing the environment in the
......@@ -248,6 +253,16 @@ class HTTPRequest(BaseRequest):
self._steps=[]
self._lazies={}
if environ.has_key('REMOTE_ADDR'):
self._client_addr = environ['REMOTE_ADDR']
if environ.has_key('HTTP_X_FORWARDED_FOR') and self._client_addr in trusted_proxies:
# REMOTE_ADDR is one of our trusted local proxies. Not really very remote at all.
# The proxy can tell us the IP of the real remote client in the forwarded-for header
self._client_addr = environ['HTTP_X_FORWARDED_FOR'].split(',')[-1].strip()
else:
self._client_addr = ''
################################################################
# Get base info first. This isn't likely to cause
# errors and might be useful to error handlers.
......@@ -1489,3 +1504,20 @@ RECORDS=8
REC=RECORD|RECORDS
EMPTY=16
CONVERTED=32
# The ZOPE_TRUSTED_PROXIES environment variable contains a colon separated
# list of front-end proxies that are trusted to supply an accurate
# X_FORWARDED_FOR header. If REMOTE_ADDR is one of the values in this list
# and it has set an X_FORWARDED_FOR header, ZPublisher copies REMOTE_ADDR
# into X_FORWARDED_BY, and the last element of the X_FORWARDED_FOR list
# into REMOTE_ADDR. X_FORWARDED_FOR is left unchanged.
# This function parses the environment variable into a module variable
#
def trusted_proxies():
proxies = os.environ.get('ZOPE_TRUSTED_PROXIES','')
proxies = proxies.split(':')
proxies = [p.strip() for p in proxies]
return tuple(proxies)
trusted_proxies = trusted_proxies()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment