home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 June / maximum-cd-2009-06.iso / DiscContents / digsby_setup.exe / lib / pyxmpp / streamtls.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-02-26  |  9.2 KB  |  314 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  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.         
  97.         while self.socket:
  98.             
  99.             try:
  100.                 r = self.socket.read()
  101.                 if r is None:
  102.                     return None
  103.             except socket.error:
  104.                 e = None
  105.                 if e.args[0] != errno.EINTR:
  106.                     raise 
  107.                 
  108.                 return None
  109.  
  110.             self._feed_reader(r)
  111.  
  112.     
  113.     def _read(self):
  114.         self._StreamTLSMixIn__logger.debug('StreamTLSMixIn._read(), socket: %r', self.socket)
  115.         if self.tls:
  116.             self._read_tls()
  117.         else:
  118.             StreamBase._read(self)
  119.  
  120.     
  121.     def _process(self):
  122.         
  123.         try:
  124.             StreamBase._process(self)
  125.         except SSLError:
  126.             e = None
  127.             self.close()
  128.             raise TLSError('TLS Error: ' + str(e))
  129.  
  130.  
  131.     
  132.     def _process_node_tls(self, xmlnode):
  133.         ns_uri = xmlnode.ns().getContent()
  134.         if ns_uri == STREAM_NS:
  135.             return False
  136.         elif ns_uri == TLS_NS:
  137.             self._process_tls_node(xmlnode)
  138.             return True
  139.         
  140.         if self.tls_settings and self.tls_settings.require and not (self.tls):
  141.             raise StreamEncryptionRequired, 'TLS encryption required and not started yet'
  142.         
  143.         return False
  144.  
  145.     
  146.     def _handle_tls_features(self):
  147.         ctxt = self.doc_in.xpathNewContext()
  148.         ctxt.setContextNode(self.features)
  149.         ctxt.xpathRegisterNs('tls', TLS_NS)
  150.         
  151.         try:
  152.             tls_n = ctxt.xpathEval('tls:starttls')
  153.             tls_required_n = ctxt.xpathEval('tls:starttls/tls:required')
  154.         finally:
  155.             ctxt.xpathFreeContext()
  156.  
  157.         if not self.tls:
  158.             if tls_required_n and not (self.tls_settings):
  159.                 raise FatalStreamError, 'StartTLS support disabled, but required by peer'
  160.             
  161.             if self.tls_settings and self.tls_settings.require and not tls_n:
  162.                 raise FatalStreamError, 'StartTLS required, but not supported by peer'
  163.             
  164.             if self.tls_settings and tls_n:
  165.                 self._StreamTLSMixIn__logger.debug('StartTLS negotiated')
  166.                 if not self.tls_available:
  167.                     raise TLSNegotiatedButNotAvailableError, 'StartTLS negotiated, but not available (M2Crypto >= 0.16 module required)'
  168.                 
  169.                 if self.initiator:
  170.                     self._request_tls()
  171.                 
  172.             else:
  173.                 self._StreamTLSMixIn__logger.debug('StartTLS not negotiated')
  174.         
  175.  
  176.     
  177.     def _request_tls(self):
  178.         self.tls_requested = 1
  179.         self.features = None
  180.         root = self.doc_out.getRootElement()
  181.         xmlnode = root.newChild(None, 'starttls', None)
  182.         ns = xmlnode.newNs(TLS_NS, None)
  183.         xmlnode.setNs(ns)
  184.         self._write_raw(xmlnode.serialize(encoding = 'UTF-8'))
  185.         xmlnode.unlinkNode()
  186.         xmlnode.freeNode()
  187.  
  188.     
  189.     def _process_tls_node(self, xmlnode):
  190.         if not (self.tls_settings) or not tls_available:
  191.             self._StreamTLSMixIn__logger.debug('Unexpected TLS node: %r' % xmlnode.serialize())
  192.             return False
  193.         
  194.         if self.initiator:
  195.             if xmlnode.name == 'failure':
  196.                 raise TLSNegotiationFailed, 'Peer failed to initialize TLS connection'
  197.             elif xmlnode.name != 'proceed' or not (self.tls_requested):
  198.                 self._StreamTLSMixIn__logger.debug('Unexpected TLS node: %r' % xmlnode.serialize())
  199.                 return False
  200.             
  201.             
  202.             try:
  203.                 self.tls_requested = 0
  204.                 self._make_tls_connection()
  205.                 self.socket = self.tls
  206.             except SSLError:
  207.                 e = None
  208.                 self.tls = None
  209.                 raise TLSError('TLS Error: ' + str(e))
  210.  
  211.             self._StreamTLSMixIn__logger.debug('Restarting XMPP stream')
  212.             self._restart_stream()
  213.             return True
  214.         else:
  215.             raise FatalStreamError, 'TLS not implemented for the receiving side yet'
  216.  
  217.     
  218.     def _make_tls_connection(self):
  219.         if not tls_available or not (self.tls_settings):
  220.             raise TLSError, 'TLS is not available'
  221.         
  222.         self.state_change('tls connecting', self.peer)
  223.         self._StreamTLSMixIn__logger.debug('Creating TLS context')
  224.         if self.tls_settings.ctx:
  225.             ctx = self.tls_settings.ctx
  226.         else:
  227.             ctx = SSL.Context('tlsv1')
  228.         verify_callback = self.tls_settings.verify_callback
  229.         if not verify_callback:
  230.             verify_callback = self.tls_default_verify_callback
  231.         
  232.         if self.tls_settings.verify_peer:
  233.             self._StreamTLSMixIn__logger.debug('verify_peer, verify_callback: %r', verify_callback)
  234.             ctx.set_verify(SSL.verify_peer, 10, verify_callback)
  235.         else:
  236.             ctx.set_verify(SSL.verify_none, 10)
  237.         if self.tls_settings.cert_file:
  238.             ctx.use_certificate_chain_file(self.tls_settings.cert_file)
  239.             if self.tls_settings.key_file:
  240.                 ctx.use_PrivateKey_file(self.tls_settings.key_file)
  241.             else:
  242.                 ctx.use_PrivateKey_file(self.tls_settings.cert_file)
  243.             ctx.check_private_key()
  244.         
  245.         if self.tls_settings.cacert_file:
  246.             
  247.             try:
  248.                 ctx.load_verify_location(self.tls_settings.cacert_file)
  249.             except AttributeError:
  250.                 ctx.load_verify_locations(self.tls_settings.cacert_file)
  251.             except:
  252.                 None<EXCEPTION MATCH>AttributeError
  253.             
  254.  
  255.         None<EXCEPTION MATCH>AttributeError
  256.         self._StreamTLSMixIn__logger.debug('Creating TLS connection')
  257.         self.tls = SSL.Connection(ctx, self.socket)
  258.         self.socket = None
  259.         self._StreamTLSMixIn__logger.debug('Setting up TLS connection')
  260.         self.tls.setup_ssl()
  261.         self._StreamTLSMixIn__logger.debug('Setting TLS connect state')
  262.         self.tls.set_connect_state()
  263.         self._StreamTLSMixIn__logger.debug('Starting TLS handshake')
  264.         self.tls.connect_ssl()
  265.         self.state_change('tls connected', self.peer)
  266.         self.tls.setblocking(0)
  267.         
  268.         try:
  269.             raise Exception
  270.         except:
  271.             pass
  272.  
  273.  
  274.     
  275.     def tls_is_certificate_valid(self, store_context):
  276.         depth = store_context.get_error_depth()
  277.         if depth > 0:
  278.             return True
  279.         
  280.         cert = store_context.get_current_cert()
  281.         cn = cert.get_subject().CN
  282.         if str(cn) != self.peer.as_utf8():
  283.             return False
  284.         
  285.         return True
  286.  
  287.     
  288.     def tls_default_verify_callback(self, ok, store_context):
  289.         
  290.         try:
  291.             self._StreamTLSMixIn__logger.debug('tls_default_verify_callback(ok=%i, store=%r)' % (ok, store_context))
  292.             X509 = X509
  293.             m2 = m2
  294.             import M2Crypto
  295.             depth = store_context.get_error_depth()
  296.             cert = store_context.get_current_cert()
  297.             cn = cert.get_subject().CN
  298.             self._StreamTLSMixIn__logger.debug('  depth: %i cert CN: %r' % (depth, cn))
  299.             if ok and not self.tls_is_certificate_valid(store_context):
  300.                 self._StreamTLSMixIn__logger.debug(u'Common name does not match peer name (%s != %s)' % (cn, self.peer.as_utf8))
  301.                 return False
  302.             
  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.