Exemple #1
0
 def __init__(self, protocol=ZD_PROTO_AUTO, timeout_connect=None, timeout_state=None):
     """<method maturity="stable">
       <summary>
         Constructor to initialize a StateBasedChainer instance.
       </summary>
       <description>
         <para>
           This constructor initializes a StateBasedChainer class by
           filling arguments with appropriate values and calling the
           inherited constructor.
         </para>
       </description>
       <metainfo>
         <arguments>
           <argument maturity="stable">
             <name>protocol</name>
             <type>
               <link id="zorp.proto.id"/>
             </type>
             <default>ZD_PROTO_AUTO</default>
             <description>
               Optional, specifies connection protocol (<parameter>
               ZD_PROTO_TCP</parameter> or <parameter>ZD_PROTO_UDP
               </parameter>), when not specified it
               defaults to the same protocol used on the
               client side.
             </description>
           </argument>
           <argument>
             <name>timeout_connect</name>
             <type>
               <integer/>
             </type>
             <default>30000</default>
             <description>
               Specifies connection timeout to be used when
               connecting to the target server.
             </description>
           </argument>
           <argument>
             <name>timeout_state</name>
             <type>
               <integer/>
             </type>
             <default>60000</default>
             <description>
               The down state of remote hosts is kept for this interval in miliseconds.
             </description>
           </argument>
         </arguments>
       </metainfo>
     </method>
     """
     super(StateBasedChainer, self).__init__(protocol, timeout_connect)
     if not timeout_state:
         timeout_state = 60000
     self.state = TimedCache('chainer-state', int((timeout_state + 999) / 1000), update_stamp=FALSE)
Exemple #2
0
	def __init__(self, protocol=ZD_PROTO_AUTO, timeout_connect=None, timeout_state=None):
		"""<method maturity="stable">
                  <summary>
                    Constructor to initialize a StateBasedChainer instance.
                  </summary>
                  <description>
                    <para>
                      This constructor initializes a StateBasedChainer class by
                      filling arguments with appropriate values and calling the
                      inherited constructor.
                    </para>
                  </description>
                  <metainfo>
                    <arguments>
                      <argument maturity="stable">
                        <name>protocol</name>
                        <type>
			  <link id="zorp.proto.id"/>
			</type>
			<default>ZD_PROTO_AUTO</default>
                        <description>
                          Optional, specifies connection protocol (<parameter>
                          ZD_PROTO_TCP</parameter> or <parameter>ZD_PROTO_UDP
                          </parameter>), when not specified it
                          defaults to the same protocol used on the
                          client side.
                        </description>
                      </argument>
                      <argument>
                        <name>timeout_connect</name>
                        <type>
                          <integer/>
			</type>
			<default>30000</default>
                        <description>
                          Specifies connection timeout to be used when
                          connecting to the target server.
                        </description>
                      </argument>
                      <argument>
                        <name>timeout_state</name>
                        <type>
			  <integer/>
			</type>
			<default>60000</default>
                        <description>
                          The down state of remote hosts is kept for this interval in miliseconds.
                        </description>
                      </argument>
                    </arguments>
                  </metainfo>
                </method>
		"""
		MultiTargetChainer.__init__(self, protocol, timeout_connect)
                if not timeout_state:
                        timeout_state = 60000
		self.state = TimedCache('chainer-state', int((timeout_state + 999) / 1000), update_stamp=FALSE)
Exemple #3
0
class StateBasedChainer(MultiTargetChainer):
    """<class maturity="stable" abstract="yes">
          <summary>
            Class encapsulating connection establishment with multiple
            target addresses and keeping down state between connects.
          </summary>
          <description>
            <para>
              This class encapsulates a real TCP/IP connection
              establishment, and is used when a top-level proxy wants to
              perform chaining. In addition to ConnectChainer, this class
              adds the capability to perform stateful, load balance
              server connections among a set of IP addresses.
            </para>
            <note>
            <para>Both the <link linkend="python.Chainer.FailoverChainer">FailoverChainer</link> 
            and <link linkend="python.Chainer.RoundRobinChainer">RoundRobinChainer</link>
             classes are derived from StateBasedChainer.</para>
            </note>
          </description>
          <metainfo>
            <attributes>
               <attribute internal="yes">
                 <name>state</name>
                 <type></type>
                 <description>Down state of target hosts.
                 </description>
               </attribute>
             </attributes>
          </metainfo>
        </class>
	"""
    def __init__(self,
                 protocol=ZD_PROTO_AUTO,
                 timeout_connect=None,
                 timeout_state=None):
        """<method maturity="stable">
                  <summary>
                    Constructor to initialize a StateBasedChainer instance.
                  </summary>
                  <description>
                    <para>
                      This constructor initializes a StateBasedChainer class by
                      filling arguments with appropriate values and calling the
                      inherited constructor.
                    </para>
                  </description>
                  <metainfo>
                    <arguments>
                      <argument maturity="stable">
                        <name>protocol</name>
                        <type>
			  <link id="zorp.proto.id"/>
			</type>
			<default>ZD_PROTO_AUTO</default>
                        <description>
                          Optional, specifies connection protocol (<parameter>
                          ZD_PROTO_TCP</parameter> or <parameter>ZD_PROTO_UDP
                          </parameter>), when not specified it
                          defaults to the same protocol used on the
                          client side.
                        </description>
                      </argument>
                      <argument>
                        <name>timeout_connect</name>
                        <type>
                          <integer/>
			</type>
			<default>30000</default>
                        <description>
                          Specifies connection timeout to be used when
                          connecting to the target server.
                        </description>
                      </argument>
                      <argument>
                        <name>timeout_state</name>
                        <type>
			  <integer/>
			</type>
			<default>60000</default>
                        <description>
                          The down state of remote hosts is kept for this interval in miliseconds.
                        </description>
                      </argument>
                    </arguments>
                  </metainfo>
                </method>
		"""
        MultiTargetChainer.__init__(self, protocol, timeout_connect)
        if not timeout_state:
            timeout_state = 60000
        self.state = TimedCache('chainer-state',
                                int((timeout_state + 999) / 1000),
                                update_stamp=FALSE)

    def getNextTarget(self, session):
        """<method internal="yes">
                </method>
                """
        while 1:
            (target_local,
             target_remote) = MultiTargetChainer.getNextTarget(self, session)

            if not target_remote:
                # we enumerated all targets
                try:
                    session.chainer_targets_enumerated = session.chainer_targets_enumerated + 1
                except AttributeError:
                    session.chainer_targets_enumerated = 1

                if not self.state or session.chainer_targets_enumerated == 2:
                    # we enumerated all our targets twice, once
                    # with state held, and then all state
                    # cleared, we were not successful, terminate
                    # target iteration
                    log(
                        None, CORE_MESSAGE, 4,
                        "All destinations are down for two full iterations, giving up;"
                    )
                    return (None, None)

## LOG ##
# This message reports that the remote end is down and Zorp stores the
# down state of the remote end, so Zorp wont try to connect to it within the
# timeout latter.
##
                log(
                    None, CORE_MESSAGE, 4,
                    "All destinations are down, clearing cache and trying again;"
                )

                # we enumerated all targets, and all of them were
                # down, clear our state and try once more
                self.state.clear()
                self.restart(session)
                continue

            is_host_down = self.state.lookup(target_remote.ip_s)
            if not is_host_down:
                return (target_local, target_remote)
            else:
                ## LOG ##
                # This message reports that the remote end is down, but Zorp does not store the
                # down state of the remote end, so Zorp will try to connect to it next time.
                ##
                log(session.session_id, CORE_MESSAGE, 4,
                    "Destination is down, skipping; remote='%s'",
                    (target_remote, ))

    def disableTarget(self, session, target_local, target_remote):
        """<method internal="yes">
                </method>
                """
        ## LOG ##
        # This message reports that the remote end is down and Zorp stores the
        # down state of the remote end, so Zorp wont try to connect to it within the
        # timeout latter.
        ##
        log(session.session_id, CORE_MESSAGE, 4,
            "Destination is down, keeping state; remote='%s'",
            (target_remote, ))
        self.state.store(target_remote.ip_s, 1)
Exemple #4
0
 def __init__(self, server_name, server_port=25, cache_timeout=60, attempt_delivery=FALSE, force_delivery_attempt=FALSE, sender_address='<>', bind_name=''):
     """<method maturity="stable">
       <summary>
       </summary>
       <description>
       </description>
       <metainfo>
       <arguments>
           <argument maturity="stable">
             <name>server_name</name>
             <type>
               <string/>
             </type>
             <description>
               Domain name of the SMTP server that will verify the addresses.
             </description>
           </argument>
           <argument maturity="stable">
             <name>server_port</name>
             <type>
               <integer/>
             </type>
             <default>25</default>
             <description>
               Port of the target server.
             </description>
           </argument>
           <argument maturity="stable">
             <name>cache_timeout</name>
             <type>
               <integer/>
             </type>
             <default>60</default>
             <description>
               How long will the result of an address verification be retained (in seconds).
             </description>
           </argument>
           <argument maturity="obsolete">
             <name>attempt_delivery</name>
             <type>
               <boolean/>
             </type>
             <default>FALSE</default>
             <description>
               Obsolete, ignored.
             </description>
           </argument>
           <argument maturity="stable">
             <name>force_delivery_attempt</name>
             <type>
               <boolean/>
             </type>
             <default>FALSE</default>
             <description>
               Force a delivery attempt even if the autodetection code otherwise
               would use VRFY. Useful if the server always returns success for VRFY.
             </description>
           </argument>
           <argument maturity="stable">
             <name>sender_address</name>
             <type>
               <string/>
             </type>
             <default>"&lt;&gt;"</default>
             <description>
               This value will be used as the mail sender for the
               attempted mail delivery. Mail delivery is attempted if
               the <parameter>force_delivery_attempt</parameter> is TRUE,
               or the recipient server does not support the VRFY command.
             </description>
           </argument>
           <argument maturity="stable">
             <name>bind_name</name>
             <type>
               <string/>
             </type>
             <default>""</default>
             <description>
               Specifies the hostname to bind to before initiating the connection to the SMTP server.
             </description>
           </argument>
         </arguments>
       </metainfo>
     </method>
     """
     super(SmtpInvalidRecipientMatcher, self).__init__()
     self.force_delivery_attempt = force_delivery_attempt
     self.server_name = server_name
     self.server_port = server_port
     self.bind_name = bind_name
     self.sender_address = sender_address
     self.cache = TimedCache('smtp_valid_recipients(%s)' % server_name, cache_timeout)
Exemple #5
0
class SmtpInvalidRecipientMatcher(AbstractMatcher):
    """<class maturity="stable" type="matcher">
      <summary>
        Class verifying the validity of the recipient addresses in E-mails.
      </summary>
      <description>
      <para>
        This class encapsulates a VRFY/RCPT based validity checker to transparently verify the existance of
        E-mail addresses. Instead of immediately sending the e-mail to the recipient SMTP server, Zorp queuries an
            independent SMTP server about the existance of the recipient e-mail address.
      </para>
      <para>
        Instances of this class can be referred to in the <parameter>recipient_matcher</parameter>
        attribute of the <link linkend="python.Smtp.SmtpProxy">SmtpProxy</link> class. The SmtpProxy
        will automatically reject unknown recipients even if the recipient SMTP
        server would accept them.
      </para>
      <example>
      <title>SmtpInvalidMatcher example</title>
      <synopsis>Python:
class SmtpRecipientMatcherProxy(SmtpProxy):
recipient_matcher="SmtpCheckrecipient"
def config(self):
super(SmtpRecipientMatcherProxy, self).config()

MatcherPolicy(name="SmtpCheckrecipient", matcher=SmtpInvalidRecipientMatcher (server_port=25, cache_timeout=60, attempt_delivery=FALSE, force_delivery_attempt=FALSE, server_name="recipientcheck.example.com"))</synopsis>
    </example>
      </description>
      <metainfo>
        <attributes/>
      </metainfo>
    </class>
    """
    def __init__(self, server_name, server_port=25, cache_timeout=60, attempt_delivery=FALSE, force_delivery_attempt=FALSE, sender_address='<>', bind_name=''):
        """<method maturity="stable">
          <summary>
          </summary>
          <description>
          </description>
          <metainfo>
          <arguments>
              <argument maturity="stable">
                <name>server_name</name>
                <type>
                  <string/>
                </type>
                <description>
                  Domain name of the SMTP server that will verify the addresses.
                </description>
              </argument>
              <argument maturity="stable">
                <name>server_port</name>
                <type>
                  <integer/>
                </type>
                <default>25</default>
                <description>
                  Port of the target server.
                </description>
              </argument>
              <argument maturity="stable">
                <name>cache_timeout</name>
                <type>
                  <integer/>
                </type>
                <default>60</default>
                <description>
                  How long will the result of an address verification be retained (in seconds).
                </description>
              </argument>
              <argument maturity="obsolete">
                <name>attempt_delivery</name>
                <type>
                  <boolean/>
                </type>
                <default>FALSE</default>
                <description>
                  Obsolete, ignored.
                </description>
              </argument>
              <argument maturity="stable">
                <name>force_delivery_attempt</name>
                <type>
                  <boolean/>
                </type>
                <default>FALSE</default>
                <description>
                  Force a delivery attempt even if the autodetection code otherwise
                  would use VRFY. Useful if the server always returns success for VRFY.
                </description>
              </argument>
              <argument maturity="stable">
                <name>sender_address</name>
                <type>
                  <string/>
                </type>
                <default>"&lt;&gt;"</default>
                <description>
                  This value will be used as the mail sender for the
                  attempted mail delivery. Mail delivery is attempted if
                  the <parameter>force_delivery_attempt</parameter> is TRUE,
                  or the recipient server does not support the VRFY command.
                </description>
              </argument>
              <argument maturity="stable">
                <name>bind_name</name>
                <type>
                  <string/>
                </type>
                <default>""</default>
                <description>
                  Specifies the hostname to bind to before initiating the connection to the SMTP server.
                </description>
              </argument>
            </arguments>
          </metainfo>
        </method>
        """
        super(SmtpInvalidRecipientMatcher, self).__init__()
        self.force_delivery_attempt = force_delivery_attempt
        self.server_name = server_name
        self.server_port = server_port
        self.bind_name = bind_name
        self.sender_address = sender_address
        self.cache = TimedCache('smtp_valid_recipients(%s)' % server_name, cache_timeout)

    def checkMatch(self, email):
        """<method internal="yes">
        </method>
        """
        # email is a fully qualified email address like [email protected]
        try:
            cached = self.cache.lookup(email)
            if cached != None:
                ## LOG ##
                # This message reports that the recipient address has been already checked and
                # Zorp uses the cached information.
                ##
                log(None, CORE_DEBUG, 6, "Cached recipient match found; email='%s', cached='%d'", (email, cached))
                if cached:
                    return TRUE
                else:
                    return FALSE
        except KeyError:
            cached = None

        try:
            ## LOG ##
            # This message reports that the recipient address has not been already checked and
            # Zorp is going to check it now directly.
            ##
            log(None, CORE_DEBUG, 6, "Recipient validity not cached, trying the direct way; email='%s'", (email))
            server = SmtpProto(self.server_name, self.server_port, bind_addr=self.bind_name)
            try:
                (smtp_code, smtp_msg) = server.ehlo()
                if smtp_code > 299:
                    (smtp_code, smtp_msg) = server.helo()
                    esmtp = FALSE
                else:
                    esmtp = TRUE
                if smtp_code > 299:
                    raise MatcherException, "Server refused our EHLO/HELO command."
                present = FALSE
                smtp_code = -1

                if not self.force_delivery_attempt and (not esmtp or server.has_extn("VRFY")):
                    log(None, CORE_DEBUG, 6, "Trying to use VRFY to check email address validity; email='%s'", (email,))
                    (smtp_code, smtp_msg) = server.verify(email)
                    present = (smtp_code < 300)
                else:
                    log(None, CORE_DEBUG, 6, "Attempting delivery to check email address validity; email='%s'", (email,))
                    (smtp_code, smtp_msg) = server.mail(self.sender_address)
                    if smtp_code == 250:
                        (smtp_code, smtp_msg) = server.rcpt(email)
                        present = (smtp_code < 300)
                    else:
                        ## LOG ##
                        # This message indicates that the sender address was rejected during the recipient address
                        # verify check and Zorp rejects the recipient address.
                        ##
                        log(None, CORE_ERROR, 3, "SMTP sender was rejected, unable to verify user existence; email='%s', server_address='%s', server_port='%d'", (email, self.server_name, self.server_port))
                        raise MatcherException, "Server has not accepted our sender (%s)." % self.sender_address
                if present:
                    ## LOG ##
                    # This message reports that the recipient address verify was successful and Zorp accepts it.
                    ##
                    log(None, CORE_INFO, 5, "Server accepted recipient; email='%s'", email)
                    # we only cache successful lookups
                    self.cache.store(email, not present)
                elif smtp_code != -1:
                    ## LOG ##
                    # This message reports that the recipient address verify was unsuccessful and Zorp rejects it.
                    ##
                    log(None, CORE_INFO, 4, "Server rejected recipient; email='%s'", email)
            finally:
                server.quit()
        except (socket.error, smtplib.SMTPException), e:
            ## LOG ##
            # This message indicates that an SMTP error occurred during the recipient address verify
            # and Zorp rejects it.
            ##
            log(None, CORE_ERROR, 3, "SMTP error during recipient validity checking; info='%s'", e)
            raise MatcherException, "SMTP error or socket failure while checking user validity (%s)" % str(e)

        # we return when we want to reject...
        return not present
Exemple #6
0
 def __init__(self,
              name=None,
              timeout=600,
              update_stamp=TRUE,
              service_equiv=FALSE,
              cleanup_threshold=100):
     """
             <method maturity="stable">
               <summary>
                 Constructor to initialize an instance of the AuthCache class.
               </summary>
               <description>
                 <para>
                   This constructor initializes and registers an AuthCache
                   instance that can be referenced in authentication
                   policies.
                 </para>
               </description>
               <metainfo>
                 <arguments>
                   <argument maturity="obsolete">
                     <name>name</name>
                     <type>
                       <string/>
                     </type>
                     <default>None</default>
                     <description>
                       The name of the authentication cache, this will be
                       used to identify this authentication cache when
                       the obsolete AuthPolicy construct is used. Setting
                       this value is not required if
                       AuthenticationPolicy is used.
                     </description>
                   </argument>
                   <argument>
                     <name>timeout</name>
                     <type>
                       <integer/>
                     </type>
                     <default>600</default>
                     <description>
                       Timeout while an authentication is assumed to be valid.
                     </description>
                   </argument>
                   <argument>
                     <name>update_stamp</name>
                     <type>
                       <boolean/>
                     </type>
                     <default>TRUE</default>
                     <description>
                       If set to <parameter>TRUE</parameter>, then cached authentications increase
                       the validity period of the authentication cache. Otherwise, the authentication
                       cache expires according to the timeout value set in
                       <xref linkend="Auth___init___timeout"/><!-- FIXME ambiguous link, should point to
                       previous attribute-->.
                     </description>
                   </argument>
                   <argument>
                     <name>service_equiv</name>
                     <type>
                       <boolean/>
                     </type>
                     <default>FALSE</default>
                     <description>If enabled, then a single authentication of a user applies to every service from that client.</description>
                   </argument>
                   <argument>
                     <name>cleanup_threshold</name>
                     <type>
                       <integer/>
                     </type>
                     <default>100</default>
                     <description>
                       When the number of entries in the cache reaches the value of
                       <parameter>cleanup_threshold</parameter>, old entries are automatically
                       deleted.
                     </description>
                   </argument>
                 </arguments>
               </metainfo>
             </method>
             """
     if name:
         self.name = name
         cache_name = 'authcache(%s)' % self.name
     else:
         cache_name = 'authcache(noname)'
     self.cache = LockedCache(
         TimedCache(cache_name, timeout, update_stamp, cleanup_threshold))
     self.service_equiv = service_equiv
     if name:
         if Globals.auth_caches.has_key(name):
             raise ValueError, "Duplicate AuthCache name: %s" % name
         Globals.auth_caches[name] = self
Exemple #7
0
 def __init__(self, server_name, server_port=25, cache_timeout=60, attempt_delivery=FALSE, force_delivery_attempt=FALSE, sender_address='<>', bind_name=''):
     """<method maturity="stable">
       <summary>
       </summary>
       <description>
       </description>
       <metainfo>
       <arguments>
           <argument maturity="stable">
             <name>server_name</name>
             <type>
               <string/>
             </type>
             <description>
               Domain name of the SMTP server that will verify the addresses.
             </description>
           </argument>
           <argument maturity="stable">
             <name>server_port</name>
             <type>
               <integer/>
             </type>
             <default>25</default>
             <description>
               Port of the target server.
             </description>
           </argument>
           <argument maturity="stable">
             <name>cache_timeout</name>
             <type>
               <integer/>
             </type>
             <default>60</default>
             <description>
               How long will the result of an address verification be retained (in seconds).
             </description>
           </argument>
           <argument maturity="obsolete">
             <name>attempt_delivery</name>
             <type>
               <boolean/>
             </type>
             <default>FALSE</default>
             <description>
               Obsolete, ignored.
             </description>
           </argument>
           <argument maturity="stable">
             <name>force_delivery_attempt</name>
             <type>
               <boolean/>
             </type>
             <default>FALSE</default>
             <description>
               Force a delivery attempt even if the autodetection code otherwise
               would use VRFY. Useful if the server always returns success for VRFY.
             </description>
           </argument>
           <argument maturity="stable">
             <name>sender_address</name>
             <type>
               <string/>
             </type>
             <default>"&lt;&gt;"</default>
             <description>
               This value will be used as the mail sender for the
               attempted mail delivery. Mail delivery is attempted if
               the <parameter>force_delivery_attempt</parameter> is TRUE,
               or the recipient server does not support the VRFY command.
             </description>
           </argument>
           <argument maturity="stable">
             <name>bind_name</name>
             <type>
               <string/>
             </type>
             <default>""</default>
             <description>
               Specifies the hostname to bind to before initiating the connection to the SMTP server.
             </description>
           </argument>
         </arguments>
       </metainfo>
     </method>
     """
     super(SmtpInvalidRecipientMatcher, self).__init__()
     self.force_delivery_attempt = force_delivery_attempt
     self.server_name = server_name
     self.server_port = server_port
     self.bind_name = bind_name
     self.sender_address = sender_address
     self.cache = TimedCache('smtp_valid_recipients(%s)' % server_name, cache_timeout)
Exemple #8
0
class SmtpInvalidRecipientMatcher(AbstractMatcher):
    """<class maturity="stable" type="matcher">
      <summary>
        Class verifying the validity of the recipient addresses in E-mails.
      </summary>
      <description>
      <para>
        This class encapsulates a VRFY/RCPT based validity checker to transparently verify the existance of
        E-mail addresses. Instead of immediately sending the e-mail to the recipient SMTP server, Zorp queuries an
            independent SMTP server about the existance of the recipient e-mail address.
      </para>
      <para>
        Instances of this class can be referred to in the <parameter>recipient_matcher</parameter>
        attribute of the <link linkend="python.Smtp.SmtpProxy">SmtpProxy</link> class. The SmtpProxy
        will automatically reject unknown recipients even if the recipient SMTP
        server would accept them.
      </para>
      <example>
      <title>SmtpInvalidMatcher example</title>
      <synopsis>Python:
class SmtpRecipientMatcherProxy(SmtpProxy):
recipient_matcher="SmtpCheckrecipient"
def config(self):
super(SmtpRecipientMatcherProxy, self).config()

MatcherPolicy(name="SmtpCheckrecipient", matcher=SmtpInvalidRecipientMatcher (server_port=25, cache_timeout=60, attempt_delivery=FALSE, force_delivery_attempt=FALSE, server_name="recipientcheck.example.com"))</synopsis>
    </example>
      </description>
      <metainfo>
        <attributes/>
      </metainfo>
    </class>
    """
    def __init__(self, server_name, server_port=25, cache_timeout=60, attempt_delivery=FALSE, force_delivery_attempt=FALSE, sender_address='<>', bind_name=''):
        """<method maturity="stable">
          <summary>
          </summary>
          <description>
          </description>
          <metainfo>
          <arguments>
              <argument maturity="stable">
                <name>server_name</name>
                <type>
                  <string/>
                </type>
                <description>
                  Domain name of the SMTP server that will verify the addresses.
                </description>
              </argument>
              <argument maturity="stable">
                <name>server_port</name>
                <type>
                  <integer/>
                </type>
                <default>25</default>
                <description>
                  Port of the target server.
                </description>
              </argument>
              <argument maturity="stable">
                <name>cache_timeout</name>
                <type>
                  <integer/>
                </type>
                <default>60</default>
                <description>
                  How long will the result of an address verification be retained (in seconds).
                </description>
              </argument>
              <argument maturity="obsolete">
                <name>attempt_delivery</name>
                <type>
                  <boolean/>
                </type>
                <default>FALSE</default>
                <description>
                  Obsolete, ignored.
                </description>
              </argument>
              <argument maturity="stable">
                <name>force_delivery_attempt</name>
                <type>
                  <boolean/>
                </type>
                <default>FALSE</default>
                <description>
                  Force a delivery attempt even if the autodetection code otherwise
                  would use VRFY. Useful if the server always returns success for VRFY.
                </description>
              </argument>
              <argument maturity="stable">
                <name>sender_address</name>
                <type>
                  <string/>
                </type>
                <default>"&lt;&gt;"</default>
                <description>
                  This value will be used as the mail sender for the
                  attempted mail delivery. Mail delivery is attempted if
                  the <parameter>force_delivery_attempt</parameter> is TRUE,
                  or the recipient server does not support the VRFY command.
                </description>
              </argument>
              <argument maturity="stable">
                <name>bind_name</name>
                <type>
                  <string/>
                </type>
                <default>""</default>
                <description>
                  Specifies the hostname to bind to before initiating the connection to the SMTP server.
                </description>
              </argument>
            </arguments>
          </metainfo>
        </method>
        """
        super(SmtpInvalidRecipientMatcher, self).__init__()
        self.force_delivery_attempt = force_delivery_attempt
        self.server_name = server_name
        self.server_port = server_port
        self.bind_name = bind_name
        self.sender_address = sender_address
        self.cache = TimedCache('smtp_valid_recipients(%s)' % server_name, cache_timeout)

    def checkMatch(self, email):
        """<method internal="yes">
        </method>
        """
        # email is a fully qualified email address like [email protected]
        try:
            cached = self.cache.lookup(email)
            if cached != None:
                ## LOG ##
                # This message reports that the recipient address has been already checked and
                # Zorp uses the cached information.
                ##
                log(None, CORE_DEBUG, 6, "Cached recipient match found; email='%s', cached='%d'", (email, cached))
                if cached:
                    return TRUE
                else:
                    return FALSE
        except KeyError:
            cached = None

        try:
            ## LOG ##
            # This message reports that the recipient address has not been already checked and
            # Zorp is going to check it now directly.
            ##
            log(None, CORE_DEBUG, 6, "Recipient validity not cached, trying the direct way; email='%s'", (email))
            server = SmtpProto(self.server_name, self.server_port, bind_addr=self.bind_name)
            try:
                (smtp_code, smtp_msg) = server.ehlo()
                if smtp_code > 299:
                    (smtp_code, smtp_msg) = server.helo()
                    esmtp = FALSE
                else:
                    esmtp = TRUE
                if smtp_code > 299:
                    raise MatcherException, "Server refused our EHLO/HELO command."
                present = FALSE
                smtp_code = -1

                if not self.force_delivery_attempt and (not esmtp or server.has_extn("VRFY")):
                    log(None, CORE_DEBUG, 6, "Trying to use VRFY to check email address validity; email='%s'", (email,))
                    (smtp_code, smtp_msg) = server.verify(email)
                    present = (smtp_code < 300)
                else:
                    log(None, CORE_DEBUG, 6, "Attempting delivery to check email address validity; email='%s'", (email,))
                    (smtp_code, smtp_msg) = server.mail(self.sender_address)
                    if smtp_code == 250:
                        (smtp_code, smtp_msg) = server.rcpt(email)
                        present = (smtp_code < 300)
                    else:
                        ## LOG ##
                        # This message indicates that the sender address was rejected during the recipient address
                        # verify check and Zorp rejects the recipient address.
                        ##
                        log(None, CORE_ERROR, 3, "SMTP sender was rejected, unable to verify user existence; email='%s', server_address='%s', server_port='%d'", (email, self.server_name, self.server_port))
                        raise MatcherException, "Server has not accepted our sender (%s)." % self.sender_address
                if present:
                    ## LOG ##
                    # This message reports that the recipient address verify was successful and Zorp accepts it.
                    ##
                    log(None, CORE_INFO, 5, "Server accepted recipient; email='%s'", email)
                    # we only cache successful lookups
                    self.cache.store(email, not present)
                elif smtp_code != -1:
                    ## LOG ##
                    # This message reports that the recipient address verify was unsuccessful and Zorp rejects it.
                    ##
                    log(None, CORE_INFO, 4, "Server rejected recipient; email='%s'", email)
            finally:
                server.quit()
        except (socket.error, smtplib.SMTPException), e:
            ## LOG ##
            # This message indicates that an SMTP error occurred during the recipient address verify
            # and Zorp rejects it.
            ##
            log(None, CORE_ERROR, 3, "SMTP error during recipient validity checking; info='%s'", e)
            raise MatcherException, "SMTP error or socket failure while checking user validity (%s)" % str(e)

        # we return when we want to reject...
        return not present
Exemple #9
0
class StateBasedChainer(MultiTargetChainer):
	"""<class maturity="stable" abstract="yes">
          <summary>
            Class encapsulating connection establishment with multiple
            target addresses and keeping down state between connects.
          </summary>
          <description>
            <para>
              This class encapsulates a real TCP/IP connection
              establishment, and is used when a top-level proxy wants to
              perform chaining. In addition to ConnectChainer, this class
              adds the capability to perform stateful, load balance
              server connections among a set of IP addresses.
            </para>
            <note>
            <para>Both the <link linkend="python.Chainer.FailoverChainer">FailoverChainer</link> 
            and <link linkend="python.Chainer.RoundRobinChainer">RoundRobinChainer</link>
             classes are derived from StateBasedChainer.</para>
            </note>
          </description>
          <metainfo>
            <attributes>
               <attribute internal="yes">
                 <name>state</name>
                 <type></type>
                 <description>Down state of target hosts.
                 </description>
               </attribute>
             </attributes>
          </metainfo>
        </class>
	"""
	def __init__(self, protocol=ZD_PROTO_AUTO, timeout_connect=None, timeout_state=None):
		"""<method maturity="stable">
                  <summary>
                    Constructor to initialize a StateBasedChainer instance.
                  </summary>
                  <description>
                    <para>
                      This constructor initializes a StateBasedChainer class by
                      filling arguments with appropriate values and calling the
                      inherited constructor.
                    </para>
                  </description>
                  <metainfo>
                    <arguments>
                      <argument maturity="stable">
                        <name>protocol</name>
                        <type>
			  <link id="zorp.proto.id"/>
			</type>
			<default>ZD_PROTO_AUTO</default>
                        <description>
                          Optional, specifies connection protocol (<parameter>
                          ZD_PROTO_TCP</parameter> or <parameter>ZD_PROTO_UDP
                          </parameter>), when not specified it
                          defaults to the same protocol used on the
                          client side.
                        </description>
                      </argument>
                      <argument>
                        <name>timeout_connect</name>
                        <type>
                          <integer/>
			</type>
			<default>30000</default>
                        <description>
                          Specifies connection timeout to be used when
                          connecting to the target server.
                        </description>
                      </argument>
                      <argument>
                        <name>timeout_state</name>
                        <type>
			  <integer/>
			</type>
			<default>60000</default>
                        <description>
                          The down state of remote hosts is kept for this interval in miliseconds.
                        </description>
                      </argument>
                    </arguments>
                  </metainfo>
                </method>
		"""
		MultiTargetChainer.__init__(self, protocol, timeout_connect)
                if not timeout_state:
                        timeout_state = 60000
		self.state = TimedCache('chainer-state', int((timeout_state + 999) / 1000), update_stamp=FALSE)

	def getNextTarget(self, session):
        	"""<method internal="yes">
                </method>
                """
		while 1:
			(target_local, target_remote) = MultiTargetChainer.getNextTarget(self, session)
			
			if not target_remote:
				# we enumerated all targets
				try:
					session.chainer_targets_enumerated = session.chainer_targets_enumerated + 1
				except AttributeError:
					session.chainer_targets_enumerated = 1
					
				if not self.state or session.chainer_targets_enumerated == 2:
					# we enumerated all our targets twice, once
					# with state held, and then all state
					# cleared, we were not successful, terminate
					# target iteration
	 				log(None, CORE_MESSAGE, 4, "All destinations are down for two full iterations, giving up;")
					return (None, None)

                                ## LOG ##
                                # This message reports that the remote end is down and Zorp stores the
                                # down state of the remote end, so Zorp wont try to connect to it within the
                                # timeout latter.
                                ##
 				log(None, CORE_MESSAGE, 4, "All destinations are down, clearing cache and trying again;")

				# we enumerated all targets, and all of them were
				# down, clear our state and try once more
				self.state.clear()
				self.restart(session)
				continue
			
			is_host_down = self.state.lookup(target_remote.ip_s)
			if not is_host_down:
				return (target_local, target_remote)
			else:
				## LOG ##
                                # This message reports that the remote end is down, but Zorp does not store the
                                # down state of the remote end, so Zorp will try to connect to it next time.
                                ##
				log(session.session_id, CORE_MESSAGE, 4, "Destination is down, skipping; remote='%s'", (target_remote,))
	
	def disableTarget(self, session, target_local, target_remote):
        	"""<method internal="yes">
                </method>
                """
 		## LOG ##
                # This message reports that the remote end is down and Zorp stores the
                # down state of the remote end, so Zorp wont try to connect to it within the
                # timeout latter.
                ##
                log(session.session_id, CORE_MESSAGE, 4, "Destination is down, keeping state; remote='%s'", (target_remote,))
                self.state.store(target_remote.ip_s, 1)