[Zope-dev] ACL patch for zope 2.6

Erik Dahl edahl@mindspring.com
Tue, 14 Jan 2003 13:53:29 -0500


This is a multi-part message in MIME format.
--------------040304050904070307090404
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

I wanted to add a little more security to a zope site that has no
firewall in front of it but is mostly for internal users.  To do this I
put a check in the accept callback of http_server.  Not sure how much
security increase this really gives but I wonder if anyone would find it
useful (or if anyone has a better solution)?  Here is the patch.  I only
added the acl to the http server, it would be easy to do for the others
as well (but I have these turned off).

-EAD


--------------040304050904070307090404
Content-Type: text/plain; x-mac-type="54455854"; x-mac-creator="74657874";
 name="zope2.6-aclpatch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="zope2.6-aclpatch"

diff -C3 -r ./z2.py /home/edahl/zope/z2.py
*** ./z2.py	2002-10-08 17:18:20.000000000 -0400
--- /home/edahl/zope/z2.py	2003-01-14 10:48:40.000000000 -0500
***************
*** 222,227 ****
--- 222,234 ----
        - The start of response output, and
        - The end of the request.
  
+   -A acl
+     Add an access control list to the HTTP server.  List should be comma 
+     delimited and can contain any part of the begining of an ip address.
+     For instnace 1.2.,3.4. would allow two class b networks 1.2.0.0/16 
+     and 3.4.0.0/16.  
+    
+ 
  Environment settings are of the form: NAME=VALUE.
  
  Note: you *must* use Python 2.1 or later!
***************
*** 332,337 ****
--- 339,350 ----
  # Use a daemon process
  USE_DAEMON = 1
  
+ # Access control list by IP
+ # each ip should be the begining of an ip 
+ # ie 1.2. would allow the class b 1.2.0.0
+ # mulitple ips should be comma delimited
+ ACL_LIST=()
+ 
  #
  ########################################################################
  
***************
*** 386,392 ****
  
  
      opts, args = getopt.getopt(sys.argv[1:],
!                                'hz:Z:t:i:a:d:u:w:W:f:p:m:Sl:2DP:rF:L:XM:C',
                                 ['icp=', 'force-http-connection-close'
                                 ])
  
--- 399,405 ----
  
  
      opts, args = getopt.getopt(sys.argv[1:],
!                                'hz:Z:t:i:a:d:u:w:W:f:p:m:Sl:2DP:rF:L:XM:CA:',
                                 ['icp=', 'force-http-connection-close'
                                 ])
  
***************
*** 470,475 ****
--- 483,490 ----
              if v=='-': v=''
              FCGI_PORT=v
          elif o=='-M': DETAILED_LOG_FILE=v
+         elif o=='-A':
+             ACL_LIST = v.split(',') 
  
  except SystemExit: sys.exit(0)
  except:
***************
*** 646,652 ****
                      ip=address,
                      port=port,
                      resolver=rs,
!                     logger_object=lg)
              except socket.error, why:
                  if why[0] == 98: # address in use
                      raise port_err % {'port':port,
--- 661,669 ----
                      ip=address,
                      port=port,
                      resolver=rs,
!                     logger_object=lg,
!                     acl_list=ACL_LIST)
! 
              except socket.error, why:
                  if why[0] == 98: # address in use
                      raise port_err % {'port':port,
diff -C3 -r ./ZServer/HTTPServer.py /home/edahl/zope/ZServer/HTTPServer.py
*** ./ZServer/HTTPServer.py	2002-10-03 22:29:49.000000000 -0400
--- /home/edahl/zope/ZServer/HTTPServer.py	2003-01-14 09:28:44.000000000 -0500
***************
*** 357,365 ****
      channel_class = zhttp_channel
      shutup=0
  
!     def __init__ (self, ip, port, resolver=None, logger_object=None):
          self.shutup=1
!         http_server.__init__(self, ip, port, resolver, logger_object)
          self.shutup=0
          self.log_info('HTTP server started at %s\n'
                        '\tHostname: %s\n\tPort: %d' % (
--- 357,366 ----
      channel_class = zhttp_channel
      shutup=0
  
!     def __init__ (self, ip, port, resolver=None, logger_object=None,
!                     acl_list=None):
          self.shutup=1
!         http_server.__init__(self, ip, port, resolver, logger_object, acl_list)
          self.shutup=0
          self.log_info('HTTP server started at %s\n'
                        '\tHostname: %s\n\tPort: %d' % (
diff -C3 -r ./ZServer/medusa/http_server.py /home/edahl/zope/ZServer/medusa/http_server.py
*** ./ZServer/medusa/http_server.py	2002-06-20 10:39:34.000000000 -0400
--- /home/edahl/zope/ZServer/medusa/http_server.py	2003-01-14 10:31:21.000000000 -0500
***************
*** 558,569 ****
      
      channel_class = http_channel
      
!     def __init__ (self, ip, port, resolver=None, logger_object=None):
          self.ip = ip
          self.port = port
          asyncore.dispatcher.__init__ (self)
          self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
!         
          self.handlers = []
          
          if not logger_object:
--- 558,571 ----
      
      channel_class = http_channel
      
!     def __init__ (self, ip, port, resolver=None, logger_object=None,
!                     acl_list=None):
          self.ip = ip
          self.port = port
          asyncore.dispatcher.__init__ (self)
          self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
!         self.acl_list = acl_list
! 
          self.handlers = []
          
          if not logger_object:
***************
*** 652,657 ****
--- 654,673 ----
              self.total_clients.decrement()
              return
  
+         # check acl to see if we accept this connection
+         if self.acl_list:
+             ip = addr[0]
+             message = 'connection from client ' + ip
+             self.log_info(message)
+             for acl in self.acl_list:
+                 if ip.find(acl) == 0:
+                     break
+             else:
+                 message += " blocked"
+                 self.log_info(message, 'warning')
+                 self.total_clients.decrement()
+                 return
+ 
          self.channel_class (self, conn, addr)
          
      def install_handler (self, handler, back=0):


--------------040304050904070307090404--