def __init__(self, name, nat, cacheable=TRUE): """ <method maturity="stable"> <summary> Constructor to initialize a NAT policy. </summary> <description> <para> This contructor initializes a NAT policy. </para> </description> <metainfo> <arguments> <argument> <name>name</name> <type> <string/> </type> <description>Name identifying the NAT policy.</description> </argument> <argument> <name>nat</name> <type> <class filter="nat" instance="yes"/> </type> <description>NAT object which performs address translation.</description> </argument> <argument> <name>cacheable</name> <type> <boolean/> </type> <default>TRUE</default> <description>Enable this parameter to cache the NAT decisions.</description> </argument> </arguments> </metainfo> </method> """ self.name = name self.nat = nat self.cacheable = cacheable if self.cacheable: self.nat_cache = ShiftCache('nat(%s)' % name, 1000) if Globals.nat_policies.has_key(name): raise ValueError, "Duplicate NATPolicy name: %s" % name Globals.nat_policies[name] = self
def __init__(self, bindto=None, services=None, **kw): """ <method maturity="stable"> <summary>Constructor to initialize a CSZoneDispatcher instance.</summary> <description> <para> This constructor initializes a CSZoneDispatcher instance and sets its initial attributes based on arguments. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>bindto</name> <type> <sockaddr existing="yes"/> </type> <description>An existing <link linkend="python.SockAddr">socket address</link> containing the IP address and port number where the Dispatcher accepts connections.</description> </argument> <argument maturity="stable"> <name>services</name> <type> <hash> <key> <tuple> <zone/> <zone/> </tuple> </key> <value> <service/> </value> </hash> </type> <guitype>HASH;STRING_zone,STRING_zone;STRING_service</guitype> <description>Client zone - server zone - service name pairs using the <parameter>(("client_zone","server_zone"):"service")</parameter> format; specifying the service to start when the dispatcher accepts a connection from the given client zone that targets the server zone.</description> </argument> <argument maturity="stable"> <name>follow_parent</name> <type> <boolean/> </type> <description>Set this parameter to <parameter>TRUE</parameter> if the dispatcher handles also the connections coming from the child zones of the selected client zones. Otherwise, the dispatcher accepts traffic only from the explicitly listed client zones.</description> </argument> </arguments> </metainfo> </method> """ self.follow_parent = kw.pop('follow_parent', FALSE) super(CSZoneDispatcher, self).__init__(bindto, None, **kw) self.services = services self.cache = ShiftCache('csdispatch(%s)' % str(self.bindto), config.options.zone_dispatcher_shift_threshold)
def __init__(self, bindto=None, services=None, **kw): """ <method maturity="stable"> <summary>Constructor to initialize a ZoneDispatcher instance.</summary> <description> <para> This constructor initializes a ZoneDispatcher instance and sets its initial attributes based on arguments. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>bindto</name> <type></type> <description>bind to this address</description> </argument> <argument maturity="stable"> <name>services</name> <type></type> <description>a mapping between zone names and services</description> </argument> <argument maturity="stable"> <name>follow_parent</name> <type></type> <description>whether to follow the administrative hieararchy when finding the correct service</description> </argument> </arguments> </metainfo> </method> """ self.follow_parent = kw.pop('follow_parent', FALSE) super(ZoneDispatcher, self).__init__(bindto, None, **kw) self.services = services self.cache = ShiftCache('sdispatch(%s)' % str(bindto), config.options.zone_dispatcher_shift_threshold)
def __init__(self, name): """ <method internal="yes"> </method> """ AbstractZone.__init__(self, name) self.domains = [] self.cache = ShiftCache('zone', config.options.zone_cache_shift_threshold)
def __init__(self, bindto=None, services=None, **kw): """ <method maturity="stable"> <summary>Constructor to initialize a ZoneDispatcher instance.</summary> <description> <para> This constructor initializes a ZoneDispatcher instance and sets its initial attributes based on arguments. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>bindto</name> <type></type> <description>bind to this address</description> </argument> <argument maturity="stable"> <name>services</name> <type></type> <description>a mapping between zone names and services</description> </argument> <argument maturity="stable"> <name>follow_parent</name> <type></type> <description>whether to follow the administrative hieararchy when finding the correct service</description> </argument> </arguments> </metainfo> </method> """ if (ZoneDispatcher.deprecated_warning): ZoneDispatcher.deprecated_warning = False log( None, CORE_DEBUG, 3, "Use of ZoneDispatcher class is deprecated, Rule should be used instead." ) self.follow_parent = kw.pop('follow_parent', FALSE) super(ZoneDispatcher, self).__init__(bindto, None, **kw) self.services = services self.cache = ShiftCache('sdispatch(%s)' % str(bindto), config.options.zone_dispatcher_shift_threshold)
class NATPolicy(object): """ <class maturity="stable" type="natpolicy"> <summary> Class encapsulating named NAT instances. </summary> <description> <para> This class encapsulates a name and an associated NAT instance. NAT policies provide a way to re-use NAT instances whithout having to define NAT mappings for each service individually. </para> <example> <title>Using Natpolicies</title> <para> The following example defines a simple NAT policy, and uses this policy for SNAT in a service.</para> <synopsis> NATPolicy(name="demo_natpolicy", nat=GeneralNAT(mapping=((InetDomain(addr="10.0.1.0/24"), InetDomain(addr="192.168.1.0/24")),))) Service(name="office_http_inter", proxy_class=HttpProxy, snat_policy="demo_natpolicy") </synopsis> </example> </description> </class> """ def __init__(self, name, nat, cacheable=TRUE): """ <method maturity="stable"> <summary> Constructor to initialize a NAT policy. </summary> <description> <para> This contructor initializes a NAT policy. </para> </description> <metainfo> <arguments> <argument> <name>name</name> <type> <string/> </type> <description>Name identifying the NAT policy.</description> </argument> <argument> <name>nat</name> <type> <class filter="nat" instance="yes"/> </type> <description>NAT object which performs address translation.</description> </argument> <argument> <name>cacheable</name> <type> <boolean/> </type> <default>TRUE</default> <description>Enable this parameter to cache the NAT decisions.</description> </argument> </arguments> </metainfo> </method> """ self.name = name self.nat = nat self.cacheable = cacheable if self.cacheable: self.nat_cache = ShiftCache('nat(%s)' % name, 1000) if Globals.nat_policies.has_key(name): raise ValueError, "Duplicate NATPolicy name: %s" % name Globals.nat_policies[name] = self def performTranslation(self, session, addrs, nat_type): """ <method internal="yes"> </method> """ if session: session_id = session.session_id else: session_id = None ## LOG ## # This message reports that the NAT type and the old address before the NAT mapping occurs. ## log(session_id, CORE_DEBUG, 4, "Before NAT mapping; nat_type='%d', src_addr='%s', dst_addr='%s'", (nat_type, str(addrs[NAT_SNAT]), str(addrs[NAT_DNAT]))) if self.cacheable: if addrs[NAT_SNAT] and addrs[NAT_DNAT]: key = (addrs[NAT_SNAT].ip_s, addrs[NAT_DNAT].ip_s) elif addrs[NAT_SNAT]: key = (addrs[NAT_SNAT].ip_s, None) elif addrs[NAT_DNAT]: key = (None, addrs[NAT_DNAT].ip_s) else: raise ValueError, "NAT without any address set" cached = self.nat_cache.lookup(key) if cached: addr = addrs[nat_type].clone(FALSE) addr.ip_s = cached else: addr = self.nat.performTranslation(session, addrs, nat_type) self.nat_cache.store(key, addr.ip_s) else: addr = self.nat.performTranslation(session, addrs, nat_type) ## LOG ## # This message reports that the NAT type and the new address after the NAT mapping occurred. ## log(session_id, CORE_DEBUG, 4, "After NAT mapping; nat_type='%d', src_addr='%s', dst_addr='%s', new_addr='%s'", (nat_type, str(addrs[NAT_SNAT]), str(addrs[NAT_DNAT]), str(addr))) return addr def getKZorpMapping(self): """ <method internal="yes"> </method> """ if hasattr(self.nat, 'getKZorpMapping'): return self.nat.getKZorpMapping() raise ValueError, "NAT class does not support KZorp representation"
class RootZone(AbstractZone): """ <class maturity="stable" internal="yes"> <summary> Class encapsulating all address-dependent hierarchies like IPv4 and IPv6. </summary> <description> <para> This class encapsulates the top of all address-dependent hierarchies. It is used to locate the address hierarchy for various address families like IPv4 and IPv6. </para> <para> An instance of this class is created at startup time in the global variable named 'root_zone' which is then used when looking up the zone of a specific address. </para> </description> <metainfo> <attributes/> </metainfo> </class> """ def __init__(self, name): """ <method internal="yes"> </method> """ AbstractZone.__init__(self, name) self.domains = [] self.cache = ShiftCache('zone', config.options.zone_cache_shift_threshold) def addDomain(self, domain_zone): """ <method internal="yes"> </method> """ self.domains.append(domain_zone) def findDomain(self, address): """ <method internal="yes"> <summary> Function to find the root Zone of the given address domain. </summary> <description> <para> This function finds the first child in self which uses domain as address domain. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>domain</name> <type>Domain instance</type> <description>class implementing address range specifics (for example InetDomain for IPv4)</description> </argument> </arguments> </metainfo> </method> """ for x in self.domains: if x.isMatchingAddress(address): return x # we never return self, because RootZone is not a real zone raise ZoneException, "No root Zone found for address domain %s" % (address, ) def addZone(self, zone): """ <method internal="yes"> </method> """ domain_root = self.findDomain(zone.domain) domain_root.addZone(zone) def findZone(self, address): """ <method internal="yes"> <summary> Function to find the most specific Zone for address. </summary> <description> <para> This function searches the address hierarchy for the most specific Zone containing 'address'. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>address</name> <type>SockAddr instance</type> <description>address we are trying to find</description> </argument> </arguments> </metainfo> </method> """ # FIXME: this is address family specific, should be separated # to its own method hash = address.ip zone = None zone = self.cache.lookup(hash) if not zone: domain_root = self.findDomain(address) if domain_root: zone = domain_root.findZone(address) self.cache.store(hash, zone) if not zone: raise ZoneException, str(address) return zone
class CSZoneDispatcher(Dispatcher): """ <class maturity="stable"> <summary>Class encapsulating the Dispatcher which starts a service by the client and server zone.</summary> <description> <para> This class is similar to a simple Dispatcher, but instead of starting a fixed service, it chooses one based on the client and the destined server zone. </para> <para> It takes a mapping of services indexed by a client and the server zone name, with an exception of the '*' zone, which matches anything. </para> <para> NOTE: the server zone might change during proxy and NAT processing, therefore the server zone used here only matches the real destination if those phases leave the server address intact. </para> <example> <title>CSZoneDispatcher example</title> <para>The following example defines a CSZoneDispatcher that starts the service called <parameter>internet_HTTP_DMZ</parameter> for connections received on the <parameter>192.168.2.1</parameter> IP address, but only if the connection comes from the <parameter>internet</parameter> zone and the destination is in the <parameter>DMZ</parameter> zone.</para> <synopsis>CSZoneDispatcher(bindto=SockAddrInet('192.168.2.1', 50080), services={("internet", "DMZ"):"internet_HTTP_DMZ"}, transparent=TRUE, backlog=255, threaded=FALSE, follow_parent=FALSE)</synopsis> </example> </description> <metainfo> <attributes> <attribute maturity="stable"> <name>services</name> <type></type> <description>services mapping indexed by zone names</description> </attribute> </attributes> </metainfo> </class> """ def __init__(self, bindto=None, services=None, **kw): """ <method maturity="stable"> <summary>Constructor to initialize a CSZoneDispatcher instance.</summary> <description> <para> This constructor initializes a CSZoneDispatcher instance and sets its initial attributes based on arguments. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>bindto</name> <type> <sockaddr existing="yes"/> </type> <description>An existing <link linkend="python.SockAddr">socket address</link> containing the IP address and port number where the Dispatcher accepts connections.</description> </argument> <argument maturity="stable"> <name>services</name> <type> <hash> <key> <tuple> <zone/> <zone/> </tuple> </key> <value> <service/> </value> </hash> </type> <guitype>HASH;STRING_zone,STRING_zone;STRING_service</guitype> <description>Client zone - server zone - service name pairs using the <parameter>(("client_zone","server_zone"):"service")</parameter> format; specifying the service to start when the dispatcher accepts a connection from the given client zone that targets the server zone.</description> </argument> <argument maturity="stable"> <name>follow_parent</name> <type> <boolean/> </type> <description>Set this parameter to <parameter>TRUE</parameter> if the dispatcher handles also the connections coming from the child zones of the selected client zones. Otherwise, the dispatcher accepts traffic only from the explicitly listed client zones.</description> </argument> </arguments> </metainfo> </method> """ self.follow_parent = kw.pop('follow_parent', FALSE) super(CSZoneDispatcher, self).__init__(bindto, None, **kw) self.services = services self.cache = ShiftCache('csdispatch(%s)' % str(self.bindto), config.options.zone_dispatcher_shift_threshold) def getService(self, session): """ <method internal="yes"> <summary>Virtual function which returns the service to be ran</summary> <description> <para> This function is called by our base class to find out the service to be used for the current session. It uses the client and the server zone name to decide which service to use. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>session</name> <type></type> <description>session we are starting</description> </argument> </arguments> </metainfo> </method> """ dest_zone = Zone.lookup(session.client_local) cache_ndx = (session.client_zone.getName(), dest_zone.getName()) cached = self.cache.lookup(cache_ndx) if cached == 0: ## LOG ## # This message indicates that no applicable service was found for this client zone in the services cache. # It is likely that there is no applicable service configured in this CSZoneListener/Receiver at all. # Check your CSZoneListener/Receiver service configuration. # @see: Listener.CSZoneListener # @see: Receiver.CSZoneReceiver ## log( None, CORE_POLICY, 2, "No applicable service found for this client & server zone (cached); bindto='%s', client_zone='%s', server_zone='%s'", (self.bindto, session.client_zone, dest_zone)) elif cached: return cached src_hierarchy = {} dst_hierarchy = {} if self.follow_parent: z = session.client_zone level = 0 while z: src_hierarchy[z.getName()] = level z = z.admin_parent level = level + 1 src_hierarchy['*'] = level max_level = level + 1 z = dest_zone level = 0 while z: dst_hierarchy[z.getName()] = level z = z.admin_parent level = level + 1 dst_hierarchy['*'] = level max_level = max(max_level, level + 1) else: src_hierarchy[session.client_zone.getName()] = 0 src_hierarchy['*'] = 1 dst_hierarchy[dest_zone.getName()] = 0 dst_hierarchy['*'] = 1 max_level = 10 best = None for spec in self.services.keys(): try: src_level = src_hierarchy[spec[0]] dst_level = dst_hierarchy[spec[1]] except KeyError: src_level = max_level dst_level = max_level if not best or \ (best_src_level > src_level) or \ (best_src_level == src_level and best_dst_level > dst_level): best = self.services[spec] best_src_level = src_level best_dst_level = dst_level s = None if best_src_level < max_level and best_dst_level < max_level: try: s = Globals.services[best] except KeyError: log(None, CORE_POLICY, 2, "No such service; service='%s'", (best)) else: ## LOG ## # This message indicates that no applicable service was found for this client zone. # Check your CSZoneListener/Receiver service configuration. # @see: Listener.CSZoneListener # @see: Receiver.CSZoneReceiver ## log( None, CORE_POLICY, 2, "No applicable service found for this client & server zone; bindto='%s', client_zone='%s', server_zone='%s'", (self.bindto, session.client_zone, dest_zone)) self.cache.store(cache_ndx, s) return s
class ZoneDispatcher(Dispatcher): """ <class maturity="stable" internal="yes"> <summary>Class encapsulating the Dispatcher which starts a service by the client zone.</summary> <description> <para> This class is similar to a simple Dispatcher, but instead of starting a fixed service, it chooses one based on the client zone. </para> <para> It takes a mapping of services indexed by a zone name, with an exception of the '*' service, which matches anything. </para> </description> <metainfo> <attributes> <attribute maturity="stable"> <name>services</name> <type> <hash> <key> <zone/> </key> <value> <service/> </value> </hash> </type> <description>services mapping indexed by zone name</description> </attribute> </attributes> </metainfo> </class> """ def __init__(self, bindto=None, services=None, **kw): """ <method maturity="stable"> <summary>Constructor to initialize a ZoneDispatcher instance.</summary> <description> <para> This constructor initializes a ZoneDispatcher instance and sets its initial attributes based on arguments. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>bindto</name> <type></type> <description>bind to this address</description> </argument> <argument maturity="stable"> <name>services</name> <type></type> <description>a mapping between zone names and services</description> </argument> <argument maturity="stable"> <name>follow_parent</name> <type></type> <description>whether to follow the administrative hieararchy when finding the correct service</description> </argument> </arguments> </metainfo> </method> """ self.follow_parent = kw.pop('follow_parent', FALSE) super(ZoneDispatcher, self).__init__(bindto, None, **kw) self.services = services self.cache = ShiftCache('sdispatch(%s)' % str(bindto), config.options.zone_dispatcher_shift_threshold) def getService(self, session): """ <method internal="yes"> <summary>Virtual function which returns the service to be ran</summary> <description> <para> This function is called by our base class to find out the service to be used for the current session. It uses the client zone name to decide which service to use. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>session</name> <type></type> <description>session we are starting</description> </argument> </arguments> </metainfo> </method> """ cache_ndx = session.client_zone.getName() cached = self.cache.lookup(cache_ndx) if cached == 0: ## LOG ## # This message indicates that no applicable service was found for this client zone in the services cache. # It is likely that there is no applicable service configured in this ZoneListener/Receiver at all. # Check your ZoneListener/Receiver service configuration. # @see: Listener.ZoneListener # @see: Receiver.ZoneReceiver ## log( None, CORE_POLICY, 2, "No applicable service found for this client zone (cached); bindto='%s', client_zone='%s'", (self.bindto, session.client_zone)) elif cached: return cached src_hierarchy = {} if self.follow_parent: z = session.client_zone level = 0 while z: src_hierarchy[z.getName()] = level z = z.admin_parent level = level + 1 src_hierarchy['*'] = level max_level = level + 1 else: src_hierarchy[session.client_zone.getName()] = 0 src_hierarchy['*'] = 1 max_level = 10 best = None for spec in self.services.keys(): try: src_level = src_hierarchy[spec] except KeyError: src_level = max_level if not best or \ (best_src_level > src_level): best = self.services[spec] best_src_level = src_level s = None if best_src_level < max_level: try: s = Globals.services[best] except KeyError: log(None, CORE_POLICY, 2, "No such service; service='%s'", (best)) else: ## LOG ## # This message indicates that no applicable service was found for this client zone. # Check your ZoneListener/Receiver service configuration. # @see: Listener.ZoneListener # @see: Receiver.ZoneReceiver ## log( None, CORE_POLICY, 2, "No applicable service found for this client zone; bindto='%s', client_zone='%s'", (self.bindto, session.client_zone)) self.cache.store(cache_ndx, s) return s
class NATPolicy(object): """ <class maturity="stable" type="natpolicy"> <summary> Class encapsulating named NAT instances. </summary> <description> <para> This class encapsulates a name and an associated NAT instance. NAT policies provide a way to re-use NAT instances whithout having to define NAT mappings for each service individually. </para> <example> <title>Using Natpolicies</title> <para> The following example defines a simple NAT policy, and uses this policy for SNAT in a service.</para> <synopsis>NATPolicy(name="demo_natpolicy", nat=GeneralNAT(mapping=((InetSubnet(addr="10.0.1.0/24"), InetSubnet(addr="192.168.1.0/24")),))) Service(name="office_http_inter", proxy_class=HttpProxy, snat_policy="demo_natpolicy")</synopsis> </example> </description> <metainfo> <attributes/> </metainfo> </class> """ def __init__(self, name, nat, cacheable=TRUE): """ <method maturity="stable"> <summary> Constructor to initialize a NAT policy. </summary> <description> <para> This contructor initializes a NAT policy. </para> </description> <metainfo> <arguments> <argument> <name>name</name> <type> <string/> </type> <description>Name identifying the NAT policy.</description> </argument> <argument> <name>nat</name> <type> <class filter="nat" instance="yes"/> </type> <description>NAT object which performs address translation.</description> </argument> <argument> <name>cacheable</name> <type> <boolean/> </type> <default>TRUE</default> <description>Enable this parameter to cache the NAT decisions.</description> </argument> </arguments> </metainfo> </method> """ self.name = name self.nat = nat self.cacheable = cacheable if self.cacheable: self.nat_cache = ShiftCache('nat(%s)' % name, 1000) if Globals.nat_policies.has_key(name): raise ValueError, "Duplicate NATPolicy name: %s" % name Globals.nat_policies[name] = self def performTranslation(self, session, addrs, nat_type): """ <method internal="yes"> </method> """ if session: session_id = session.session_id else: session_id = None ## LOG ## # This message reports that the NAT type and the old address before the NAT mapping occurs. ## log(session_id, CORE_DEBUG, 4, "Before NAT mapping; nat_type='%d', src_addr='%s', dst_addr='%s'", (nat_type, str(addrs[NAT_SNAT]), str(addrs[NAT_DNAT]))) if self.cacheable: if addrs[NAT_SNAT] and addrs[NAT_DNAT]: key = (addrs[NAT_SNAT].ip_s, addrs[NAT_DNAT].ip_s) elif addrs[NAT_SNAT]: key = (addrs[NAT_SNAT].ip_s, None) elif addrs[NAT_DNAT]: key = (None, addrs[NAT_DNAT].ip_s) else: raise ValueError, "NAT without any address set" cached = self.nat_cache.lookup(key) if cached: addr = cached.clone(FALSE) addr.port = addrs[nat_type].port else: addr = self.nat.performTranslation(session, addrs, nat_type) self.nat_cache.store(key, addr.clone(FALSE) if addr else None) else: addr = self.nat.performTranslation(session, addrs, nat_type) ## LOG ## # This message reports that the NAT type and the new address after the NAT mapping occurred. ## log( session_id, CORE_DEBUG, 4, "After NAT mapping; nat_type='%d', src_addr='%s', dst_addr='%s', new_addr='%s'", (nat_type, str(addrs[NAT_SNAT]), str(addrs[NAT_DNAT]), str(addr))) return addr def getKZorpMapping(self): """ <method internal="yes"> </method> """ if hasattr(self.nat, 'getKZorpMapping'): return self.nat.getKZorpMapping() raise ValueError, "NAT class does not support KZorp representation"
class CSZoneDispatcher(Dispatcher): """ <class maturity="stable"> <summary>Class encapsulating the Dispatcher which starts a service by the client and server zone.</summary> <description> <para> This class is similar to a simple Dispatcher, but instead of starting a fixed service, it chooses one based on the client and the destined server zone. </para> <para> It takes a mapping of services indexed by a client and the server zone name, with an exception of the '*' zone, which matches anything. </para> <para> NOTE: the server zone might change during proxy and NAT processing, therefore the server zone used here only matches the real destination if those phases leave the server address intact. </para> <example> <title>CSZoneDispatcher example</title> <para>The following example defines a CSZoneDispatcher that starts the service called <parameter>internet_HTTP_DMZ</parameter> for connections received on the <parameter>192.168.2.1</parameter> IP address, but only if the connection comes from the <parameter>internet</parameter> zone and the destination is in the <parameter>DMZ</parameter> zone.</para> <synopsis>CSZoneDispatcher(bindto=SockAddrInet('192.168.2.1', 50080), services={("internet", "DMZ"):"internet_HTTP_DMZ"}, transparent=TRUE, backlog=255, threaded=FALSE, follow_parent=FALSE)</synopsis> </example> </description> <metainfo> <attributes> <attribute maturity="stable"> <name>services</name> <type></type> <description>services mapping indexed by zone names</description> </attribute> </attributes> </metainfo> </class> """ deprecated_warning = True def __init__(self, bindto=None, services=None, **kw): """ <method maturity="stable"> <summary>Constructor to initialize a CSZoneDispatcher instance.</summary> <description> <para> This constructor initializes a CSZoneDispatcher instance and sets its initial attributes based on arguments. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>bindto</name> <type> <sockaddr existing="yes"/> </type> <description>An existing <link linkend="python.SockAddr">socket address</link> containing the IP address and port number where the Dispatcher accepts connections.</description> </argument> <argument maturity="stable"> <name>services</name> <type> <hash> <key> <tuple> <zone/> <zone/> </tuple> </key> <value> <service/> </value> </hash> </type> <guitype>HASH;STRING_zone,STRING_zone;STRING_service</guitype> <description>Client zone - server zone - service name pairs using the <parameter>(("client_zone","server_zone"):"service")</parameter> format; specifying the service to start when the dispatcher accepts a connection from the given client zone that targets the server zone.</description> </argument> <argument maturity="stable"> <name>follow_parent</name> <type> <boolean/> </type> <description>Set this parameter to <parameter>TRUE</parameter> if the dispatcher handles also the connections coming from the child zones of the selected client zones. Otherwise, the dispatcher accepts traffic only from the explicitly listed client zones.</description> </argument> </arguments> </metainfo> </method> """ if (CSZoneDispatcher.deprecated_warning): CSZoneDispatcher.deprecated_warning = False log(None, CORE_DEBUG, 3, "Use of CSZoneDispatcher class is deprecated, Rule should be used instead.") self.follow_parent = kw.pop('follow_parent', FALSE) super(CSZoneDispatcher, self).__init__(bindto, None, **kw) self.services = services self.cache = ShiftCache('csdispatch(%s)' % str(self.bindto), config.options.zone_dispatcher_shift_threshold) def _getSession(self, client_stream, client_local, client_listen, client_address): """ <method internal="yes"> <summary>Virtual function which returns the service to be ran</summary> <description> <para> This function is called by our base class to find out the service to be used for the current client_info. It uses the client and the server zone name to decide which service to use. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>client_info</name> <type></type> <description>Session information</description> </argument> </arguments> </metainfo> </method> """ dest_zone = Zone.lookup(client_local) client_zone = Zone.lookup(client_address) cache_ndx = (client_zone.getName(), dest_zone.getName()) cached = self.cache.lookup(cache_ndx) if cached == 0: ## LOG ## # This message indicates that no applicable service was found for this client zone in the services cache. # It is likely that there is no applicable service configured in this CSZoneListener/Receiver at all. # Check your CSZoneListener/Receiver service configuration. # @see: Listener.CSZoneListener # @see: Receiver.CSZoneReceiver ## log(None, CORE_POLICY, 2, "No applicable service found for this client & server zone (cached); bindto='%s', client_zone='%s', server_zone='%s'", (self.bindto, client_zone, dest_zone)) elif cached: return MasterSession(cached, client_stream, client_local, client_listen, client_address, client_zone = client_zone, instance_id=getInstanceId(cached.name)) src_hierarchy = {} dst_hierarchy = {} if self.follow_parent: z = client_zone level = 0 while z: src_hierarchy[z.getName()] = level z = z.admin_parent level = level + 1 src_hierarchy['*'] = level max_level = level + 1 z = dest_zone level = 0 while z: dst_hierarchy[z.getName()] = level z = z.admin_parent level = level + 1 dst_hierarchy['*'] = level max_level = max(max_level, level + 1) else: src_hierarchy[client_zone.getName()] = 0 src_hierarchy['*'] = 1 dst_hierarchy[dest_zone.getName()] = 0 dst_hierarchy['*'] = 1 max_level = 10 best = None for spec in self.services.keys(): try: src_level = src_hierarchy[spec[0]] dst_level = dst_hierarchy[spec[1]] except KeyError: src_level = max_level dst_level = max_level if not best or \ (best_src_level > src_level) or \ (best_src_level == src_level and best_dst_level > dst_level): best = self.services[spec] best_src_level = src_level best_dst_level = dst_level service = None if best is not None and best_src_level < max_level and best_dst_level < max_level: try: service = Globals.services[best] except KeyError: log(None, CORE_POLICY, 2, "No such service; service='%s'", (best)) else: ## LOG ## # This message indicates that no applicable service was found for this client zone. # Check your CSZoneListener/Receiver service configuration. # @see: Listener.CSZoneListener # @see: Receiver.CSZoneReceiver ## log(None, CORE_POLICY, 2, "No applicable service found for this client & server zone; bindto='%s', client_zone='%s', server_zone='%s'", (self.bindto, client_zone, dest_zone)) if service is None: return None self.cache.store(cache_ndx, service) return MasterSession(service, client_stream, client_local, client_listen, client_address, client_zone = client_zone, instance_id=getInstanceId(service.name))
class ZoneDispatcher(Dispatcher): """ <class maturity="stable" internal="yes"> <summary>Class encapsulating the Dispatcher which starts a service by the client zone.</summary> <description> <para> This class is similar to a simple Dispatcher, but instead of starting a fixed service, it chooses one based on the client zone. </para> <para> It takes a mapping of services indexed by a zone name, with an exception of the '*' service, which matches anything. </para> </description> <metainfo> <attributes> <attribute maturity="stable"> <name>services</name> <type> <hash> <key> <zone/> </key> <value> <service/> </value> </hash> </type> <description>services mapping indexed by zone name</description> </attribute> </attributes> </metainfo> </class> """ deprecated_warning = True def __init__(self, bindto=None, services=None, **kw): """ <method maturity="stable"> <summary>Constructor to initialize a ZoneDispatcher instance.</summary> <description> <para> This constructor initializes a ZoneDispatcher instance and sets its initial attributes based on arguments. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>bindto</name> <type></type> <description>bind to this address</description> </argument> <argument maturity="stable"> <name>services</name> <type></type> <description>a mapping between zone names and services</description> </argument> <argument maturity="stable"> <name>follow_parent</name> <type></type> <description>whether to follow the administrative hieararchy when finding the correct service</description> </argument> </arguments> </metainfo> </method> """ if (ZoneDispatcher.deprecated_warning): ZoneDispatcher.deprecated_warning = False log(None, CORE_DEBUG, 3, "Use of ZoneDispatcher class is deprecated, Rule should be used instead.") self.follow_parent = kw.pop('follow_parent', FALSE) super(ZoneDispatcher, self).__init__(bindto, None, **kw) self.services = services self.cache = ShiftCache('sdispatch(%s)' % str(bindto), config.options.zone_dispatcher_shift_threshold) def _getSession(self, client_stream, client_local, client_listen, client_address): """ <method internal="yes"> <summary>Virtual function which returns the service to be ran</summary> <description> <para> This function is called by our base class to find out the service to be used. It uses the client zone name to decide which service to use. </para> </description> <metainfo> <arguments> <argument maturity="stable"> <name>client_info</name> <type></type> <description>Session information</description> </argument> </arguments> </metainfo> </method> """ client_zone = Zone.lookup(client_address) cache_ndx = client_zone.getName() cached = self.cache.lookup(cache_ndx) if cached == 0: ## LOG ## # This message indicates that no applicable service was found for this client zone in the services cache. # It is likely that there is no applicable service configured in this ZoneListener/Receiver at all. # Check your ZoneListener/Receiver service configuration. # @see: Listener.ZoneListener # @see: Receiver.ZoneReceiver ## log(None, CORE_POLICY, 2, "No applicable service found for this client zone (cached); bindto='%s', client_zone='%s'", (self.bindto, client_zone)) elif cached: return MasterSession(cached, client_stream, client_local, client_listen, client_address, client_zone = client_zone, instance_id=getInstanceId(cached.name)) src_hierarchy = {} if self.follow_parent: z = client_zone level = 0 while z: src_hierarchy[z.getName()] = level z = z.admin_parent level = level + 1 src_hierarchy['*'] = level max_level = level + 1 else: src_hierarchy[client_zone.getName()] = 0 src_hierarchy['*'] = 1 max_level = 10 best = None for spec in self.services.keys(): try: src_level = src_hierarchy[spec] except KeyError: src_level = max_level if not best or \ (best_src_level > src_level): best = self.services[spec] best_src_level = src_level service = None if best is not None and best_src_level < max_level: try: service = Globals.services[best] except KeyError: log(None, CORE_POLICY, 2, "No such service; service='%s'", (best)) else: ## LOG ## # This message indicates that no applicable service was found for this client zone. # Check your ZoneListener/Receiver service configuration. # @see: Listener.ZoneListener # @see: Receiver.ZoneReceiver ## log(None, CORE_POLICY, 2, "No applicable service found for this client zone; bindto='%s', client_zone='%s'", (self.bindto, client_zone)) if service is None: return None self.cache.store(cache_ndx, service) return MasterSession(service, client_stream, client_local, client_listen, client_address, client_zone = client_zone, instance_id=getInstanceId(service.name))
(for example, the IP addresses and zone of the server and the client, and the username and group memberships of the user when authentication is used). Other components of Zorp refer to this data when making various policy-based decisions. </para> </description> <metainfo/> </module> """ import Zorp from Zorp import * from Zone import root_zone from Cache import ShiftCache inbound_cache = ShiftCache('inbound_cache', config.options.inbound_service_cache_threshold) outbound_cache = ShiftCache('outbound_cache', config.options.outbound_service_cache_threshold) class AbstractSession: """ <class maturity="stable" abstract="yes" internal="yes"> <summary> Class encapsulating an abstract session for different types (master, or stacked). </summary> <description> <para> Abstract base class for different session types (master, or stacked), both MasterSession and StackedSession are derived from this class. </para> </description> <metainfo>