home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 February / maximum-cd-2011-02.iso / DiscContents / digsby_setup85.exe / lib / pyxmpp / streamtls.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-11-24  |  9.2 KB  |  314 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. __revision__ = '$Id: streamtls.py 681 2008-12-05 07:18:41Z jajcus $'
  5. __docformat__ = 'restructuredtext en'
  6. import socket
  7. import sys
  8. import errno
  9. import logging
  10. from pyxmpp.streambase import StreamBase, STREAM_NS
  11. from pyxmpp.streambase import FatalStreamError, StreamEncryptionRequired
  12. from pyxmpp.exceptions import TLSNegotiationFailed, TLSError, TLSNegotiatedButNotAvailableError
  13.  
  14. try:
  15.     import M2Crypto
  16.     if M2Crypto.version_info < (0, 16):
  17.         tls_available = 0
  18.     else:
  19.         from M2Crypto import SSL
  20.         from M2Crypto.SSL import SSLError
  21.         import M2Crypto.SSL.cb as M2Crypto
  22.         tls_available = 1
  23. except ImportError:
  24.     tls_available = 0
  25.  
  26. if not tls_available:
  27.     
  28.     class SSLError(Exception):
  29.         pass
  30.  
  31.  
  32. TLS_NS = 'urn:ietf:params:xml:ns:xmpp-tls'
  33.  
  34. class TLSSettings:
  35.     
  36.     def __init__(self, require = False, verify_peer = True, cert_file = None, key_file = None, cacert_file = None, verify_callback = None, ctx = None):
  37.         self.require = require
  38.         self.ctx = ctx
  39.         self.verify_peer = verify_peer
  40.         self.cert_file = cert_file
  41.         self.cacert_file = cacert_file
  42.         self.key_file = key_file
  43.         self.verify_callback = verify_callback
  44.  
  45.  
  46.  
  47. class StreamTLSMixIn:
  48.     tls_available = tls_available
  49.     
  50.     def __init__(self, tls_settings = None):
  51.         self.tls_settings = tls_settings
  52.         self._StreamTLSMixIn__logger = logging.getLogger('pyxmpp.StreamTLSMixIn')
  53.  
  54.     
  55.     def _reset_tls(self):
  56.         self.tls = None
  57.         self.tls_requested = False
  58.  
  59.     
  60.     def _make_stream_tls_features(self, features):
  61.         if self.tls_settings and not (self.tls):
  62.             tls = features.newChild(None, 'starttls', None)
  63.             ns = tls.newNs(TLS_NS, None)
  64.             tls.setNs(ns)
  65.             if self.tls_settings.require:
  66.                 tls.newChild(None, 'required', None)
  67.             
  68.         
  69.         return features
  70.  
  71.     
  72.     def _write_raw(self, data):
  73.         logging.getLogger('pyxmpp.Stream.out').debug('OUT: %r', data)
  74.         
  75.         try:
  76.             if self.tls:
  77.                 self.tls.setblocking(True)
  78.             
  79.             if self.socket:
  80.                 self.socket.send(data)
  81.             
  82.             if self.tls:
  83.                 self.tls.setblocking(False)
  84.         except (IOError, OSError, socket.error):
  85.             e = None
  86.             raise FatalStreamError('IO Error: ' + str(e))
  87.         except SSLError:
  88.             e = None
  89.             raise TLSError('TLS Error: ' + str(e))
  90.  
  91.  
  92.     
  93.     def _read_tls(self):
  94.         if self.eof:
  95.             return None
  96.         while self.socket:
  97.             
  98.             try:
  99.                 r = self.socket.read()
  100.                 if r is None:
  101.                     return None
  102.             except socket.error:
  103.                 self.eof
  104.                 e = self.eof
  105.                 if e.args[0] != errno.EINTR:
  106.                     raise 
  107.                 e.args[0] != errno.EINTR
  108.                 return None
  109.  
  110.             self._feed_reader(r)
  111.             continue
  112.             self.eof
  113.  
  114.     
  115.     def _read(self):
  116.         self._StreamTLSMixIn__logger.debug('StreamTLSMixIn._read(), socket: %r', self.socket)
  117.         if self.tls:
  118.             self._read_tls()
  119.         else:
  120.             StreamBase._read(self)
  121.  
  122.     
  123.     def _process(self):
  124.         
  125.         try:
  126.             StreamBase._process(self)
  127.         except SSLError:
  128.             e = None
  129.             self.close()
  130.             raise TLSError('TLS Error: ' + str(e))
  131.  
  132.  
  133.     
  134.     def _process_node_tls(self, xmlnode):
  135.         ns_uri = xmlnode.ns().getContent()
  136.         if ns_uri == STREAM_NS:
  137.             return False
  138.         if ns_uri == TLS_NS:
  139.             self._process_tls_node(xmlnode)
  140.             return True
  141.         if self.tls_settings and self.tls_settings.require and not (self.tls):
  142.             raise StreamEncryptionRequired, 'TLS encryption required and not started yet'
  143.         not (self.tls)
  144.         return False
  145.  
  146.     
  147.     def _handle_tls_features(self):
  148.         ctxt = self.doc_in.xpathNewContext()
  149.         ctxt.setContextNode(self.features)
  150.         ctxt.xpathRegisterNs('tls', TLS_NS)
  151.         
  152.         try:
  153.             tls_n = ctxt.xpathEval('tls:starttls')
  154.             tls_required_n = ctxt.xpathEval('tls:starttls/tls:required')
  155.         finally:
  156.             ctxt.xpathFreeContext()
  157.  
  158.         if not self.tls:
  159.             if tls_required_n and not (self.tls_settings):
  160.                 raise FatalStreamError, 'StartTLS support disabled, but required by peer'
  161.             not (self.tls_settings)
  162.             if self.tls_settings and self.tls_settings.require and not tls_n:
  163.                 raise FatalStreamError, 'StartTLS required, but not supported by peer'
  164.             not tls_n
  165.             if self.tls_settings and tls_n:
  166.                 self._StreamTLSMixIn__logger.debug('StartTLS negotiated')
  167.                 if not self.tls_available:
  168.                     raise TLSNegotiatedButNotAvailableError, 'StartTLS negotiated, but not available (M2Crypto >= 0.16 module required)'
  169.                 self.tls_available
  170.                 if self.initiator:
  171.                     self._request_tls()
  172.                 
  173.             else:
  174.                 self._StreamTLSMixIn__logger.debug('StartTLS not negotiated')
  175.         
  176.  
  177.     
  178.     def _request_tls(self):
  179.         self.tls_requested = 1
  180.         self.features = None
  181.         root = self.doc_out.getRootElement()
  182.         xmlnode = root.newChild(None, 'starttls', None)
  183.         ns = xmlnode.newNs(TLS_NS, None)
  184.         xmlnode.setNs(ns)
  185.         self._write_raw(xmlnode.serialize(encoding = 'UTF-8'))
  186.         xmlnode.unlinkNode()
  187.         xmlnode.freeNode()
  188.  
  189.     
  190.     def _process_tls_node(self, xmlnode):
  191.         if not (self.tls_settings) or not tls_available:
  192.             self._StreamTLSMixIn__logger.debug('Unexpected TLS node: %r' % xmlnode.serialize())
  193.             return False
  194.         if self.initiator:
  195.             if xmlnode.name == 'failure':
  196.                 raise TLSNegotiationFailed, 'Peer failed to initialize TLS connection'
  197.             xmlnode.name == 'failure'
  198.             if xmlnode.name != 'proceed' or not (self.tls_requested):
  199.                 self._StreamTLSMixIn__logger.debug('Unexpected TLS node: %r' % xmlnode.serialize())
  200.                 return False
  201.             
  202.             try:
  203.                 self.tls_requested = 0
  204.                 self._make_tls_connection()
  205.                 self.socket = self.tls
  206.             except SSLError:
  207.                 not (self.tls_requested)
  208.                 e = not (self.tls_requested)
  209.                 not tls_available
  210.                 self.tls = None
  211.                 raise TLSError('TLS Error: ' + str(e))
  212.             except:
  213.                 not (self.tls_requested)
  214.  
  215.             self._StreamTLSMixIn__logger.debug('Restarting XMPP stream')
  216.             self._restart_stream()
  217.             return True
  218.         raise FatalStreamError, 'TLS not implemented for the receiving side yet'
  219.  
  220.     
  221.     def _make_tls_connection(self):
  222.         if not tls_available or not (self.tls_settings):
  223.             raise TLSError, 'TLS is not available'
  224.         not (self.tls_settings)
  225.         self.state_change('tls connecting', self.peer)
  226.         self._StreamTLSMixIn__logger.debug('Creating TLS context')
  227.         if self.tls_settings.ctx:
  228.             ctx = self.tls_settings.ctx
  229.         else:
  230.             ctx = SSL.Context('tlsv1')
  231.         verify_callback = self.tls_settings.verify_callback
  232.         if not verify_callback:
  233.             verify_callback = self.tls_default_verify_callback
  234.         
  235.         if self.tls_settings.verify_peer:
  236.             self._StreamTLSMixIn__logger.debug('verify_peer, verify_callback: %r', verify_callback)
  237.             ctx.set_verify(SSL.verify_peer, 10, verify_callback)
  238.         else:
  239.             ctx.set_verify(SSL.verify_none, 10)
  240.         if self.tls_settings.cert_file:
  241.             ctx.use_certificate_chain_file(self.tls_settings.cert_file)
  242.             if self.tls_settings.key_file:
  243.                 ctx.use_PrivateKey_file(self.tls_settings.key_file)
  244.             else:
  245.                 ctx.use_PrivateKey_file(self.tls_settings.cert_file)
  246.             ctx.check_private_key()
  247.         
  248.         if self.tls_settings.cacert_file:
  249.             
  250.             try:
  251.                 ctx.load_verify_location(self.tls_settings.cacert_file)
  252.             except AttributeError:
  253.                 ctx.load_verify_locations(self.tls_settings.cacert_file)
  254.             except:
  255.                 None<EXCEPTION MATCH>AttributeError
  256.             
  257.  
  258.         None<EXCEPTION MATCH>AttributeError
  259.         self._StreamTLSMixIn__logger.debug('Creating TLS connection')
  260.         self.tls = SSL.Connection(ctx, self.socket)
  261.         self.socket = None
  262.         self._StreamTLSMixIn__logger.debug('Setting up TLS connection')
  263.         self.tls.setup_ssl()
  264.         self._StreamTLSMixIn__logger.debug('Setting TLS connect state')
  265.         self.tls.set_connect_state()
  266.         self._StreamTLSMixIn__logger.debug('Starting TLS handshake')
  267.         self.tls.connect_ssl()
  268.         self.state_change('tls connected', self.peer)
  269.         self.tls.setblocking(0)
  270.         
  271.         try:
  272.             raise Exception
  273.         except:
  274.             pass
  275.  
  276.  
  277.     
  278.     def tls_is_certificate_valid(self, store_context):
  279.         depth = store_context.get_error_depth()
  280.         if depth > 0:
  281.             return True
  282.         cert = store_context.get_current_cert()
  283.         cn = cert.get_subject().CN
  284.         if str(cn) != self.peer.as_utf8():
  285.             return False
  286.         return True
  287.  
  288.     
  289.     def tls_default_verify_callback(self, ok, store_context):
  290.         
  291.         try:
  292.             self._StreamTLSMixIn__logger.debug('tls_default_verify_callback(ok=%i, store=%r)' % (ok, store_context))
  293.             X509 = X509
  294.             m2 = m2
  295.             import M2Crypto
  296.             depth = store_context.get_error_depth()
  297.             cert = store_context.get_current_cert()
  298.             cn = cert.get_subject().CN
  299.             self._StreamTLSMixIn__logger.debug('  depth: %i cert CN: %r' % (depth, cn))
  300.             if ok and not self.tls_is_certificate_valid(store_context):
  301.                 self._StreamTLSMixIn__logger.debug(u'Common name does not match peer name (%s != %s)' % (cn, self.peer.as_utf8))
  302.                 return False
  303.             return ok
  304.         except:
  305.             self._StreamTLSMixIn__logger.exception('Exception caught')
  306.             raise 
  307.  
  308.  
  309.     
  310.     def get_tls_connection(self):
  311.         return self.tls
  312.  
  313.  
  314.