home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / lib / python2.6 / ssl.py < prev    next >
Encoding:
Python Source  |  2010-12-26  |  14.3 KB  |  440 lines

  1. # Wrapper module for _ssl, providing some additional facilities
  2. # implemented in Python.  Written by Bill Janssen.
  3.  
  4. """\
  5. This module provides some more Pythonic support for SSL.
  6.  
  7. Object types:
  8.  
  9.   SSLSocket -- subtype of socket.socket which does SSL over the socket
  10.  
  11. Exceptions:
  12.  
  13.   SSLError -- exception raised for I/O errors
  14.  
  15. Functions:
  16.  
  17.   cert_time_to_seconds -- convert time string used for certificate
  18.                           notBefore and notAfter functions to integer
  19.                           seconds past the Epoch (the time values
  20.                           returned from time.time())
  21.  
  22.   fetch_server_certificate (HOST, PORT) -- fetch the certificate provided
  23.                           by the server running on HOST at port PORT.  No
  24.                           validation of the certificate is performed.
  25.  
  26. Integer constants:
  27.  
  28. SSL_ERROR_ZERO_RETURN
  29. SSL_ERROR_WANT_READ
  30. SSL_ERROR_WANT_WRITE
  31. SSL_ERROR_WANT_X509_LOOKUP
  32. SSL_ERROR_SYSCALL
  33. SSL_ERROR_SSL
  34. SSL_ERROR_WANT_CONNECT
  35.  
  36. SSL_ERROR_EOF
  37. SSL_ERROR_INVALID_ERROR_CODE
  38.  
  39. The following group define certificate requirements that one side is
  40. allowing/requiring from the other side:
  41.  
  42. CERT_NONE - no certificates from the other side are required (or will
  43.             be looked at if provided)
  44. CERT_OPTIONAL - certificates are not required, but if provided will be
  45.                 validated, and if validation fails, the connection will
  46.                 also fail
  47. CERT_REQUIRED - certificates are required, and will be validated, and
  48.                 if validation fails, the connection will also fail
  49.  
  50. The following constants identify various SSL protocol variants:
  51.  
  52. PROTOCOL_SSLv2
  53. PROTOCOL_SSLv3
  54. PROTOCOL_SSLv23
  55. PROTOCOL_TLSv1
  56. """
  57.  
  58. import textwrap
  59.  
  60. import _ssl             # if we can't import it, let the error propagate
  61.  
  62. from _ssl import SSLError
  63. from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
  64. from _ssl import PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1
  65. from _ssl import RAND_status, RAND_egd, RAND_add
  66. from _ssl import \
  67.      SSL_ERROR_ZERO_RETURN, \
  68.      SSL_ERROR_WANT_READ, \
  69.      SSL_ERROR_WANT_WRITE, \
  70.      SSL_ERROR_WANT_X509_LOOKUP, \
  71.      SSL_ERROR_SYSCALL, \
  72.      SSL_ERROR_SSL, \
  73.      SSL_ERROR_WANT_CONNECT, \
  74.      SSL_ERROR_EOF, \
  75.      SSL_ERROR_INVALID_ERROR_CODE
  76.  
  77. from socket import socket, _fileobject, _delegate_methods
  78. from socket import error as socket_error
  79. from socket import getnameinfo as _getnameinfo
  80. import base64        # for DER-to-PEM translation
  81. import errno
  82.  
  83. class SSLSocket(socket):
  84.  
  85.     """This class implements a subtype of socket.socket that wraps
  86.     the underlying OS socket in an SSL context when necessary, and
  87.     provides read and write methods over that channel."""
  88.  
  89.     def __init__(self, sock, keyfile=None, certfile=None,
  90.                  server_side=False, cert_reqs=CERT_NONE,
  91.                  ssl_version=PROTOCOL_SSLv23, ca_certs=None,
  92.                  do_handshake_on_connect=True,
  93.                  suppress_ragged_eofs=True):
  94.         socket.__init__(self, _sock=sock._sock)
  95.         # The initializer for socket overrides the methods send(), recv(), etc.
  96.         # in the instancce, which we don't need -- but we want to provide the
  97.         # methods defined in SSLSocket.
  98.         for attr in _delegate_methods:
  99.             try:
  100.                 delattr(self, attr)
  101.             except AttributeError:
  102.                 pass
  103.  
  104.         if certfile and not keyfile:
  105.             keyfile = certfile
  106.         # see if it's connected
  107.         try:
  108.             socket.getpeername(self)
  109.         except socket_error, e:
  110.             if e.errno != errno.ENOTCONN:
  111.                 raise
  112.             # no, no connection yet
  113.             self._sslobj = None
  114.         else:
  115.             # yes, create the SSL object
  116.             self._sslobj = _ssl.sslwrap(self._sock, server_side,
  117.                                         keyfile, certfile,
  118.                                         cert_reqs, ssl_version, ca_certs)
  119.             if do_handshake_on_connect:
  120.                 self.do_handshake()
  121.         self.keyfile = keyfile
  122.         self.certfile = certfile
  123.         self.cert_reqs = cert_reqs
  124.         self.ssl_version = ssl_version
  125.         self.ca_certs = ca_certs
  126.         self.do_handshake_on_connect = do_handshake_on_connect
  127.         self.suppress_ragged_eofs = suppress_ragged_eofs
  128.         self._makefile_refs = 0
  129.  
  130.     def read(self, len=1024):
  131.  
  132.         """Read up to LEN bytes and return them.
  133.         Return zero-length string on EOF."""
  134.  
  135.         try:
  136.             return self._sslobj.read(len)
  137.         except SSLError, x:
  138.             if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
  139.                 return ''
  140.             else:
  141.                 raise
  142.  
  143.     def write(self, data):
  144.  
  145.         """Write DATA to the underlying SSL channel.  Returns
  146.         number of bytes of DATA actually transmitted."""
  147.  
  148.         return self._sslobj.write(data)
  149.  
  150.     def getpeercert(self, binary_form=False):
  151.  
  152.         """Returns a formatted version of the data in the
  153.         certificate provided by the other end of the SSL channel.
  154.         Return None if no certificate was provided, {} if a
  155.         certificate was provided, but not validated."""
  156.  
  157.         return self._sslobj.peer_certificate(binary_form)
  158.  
  159.     def cipher(self):
  160.  
  161.         if not self._sslobj:
  162.             return None
  163.         else:
  164.             return self._sslobj.cipher()
  165.  
  166.     def send(self, data, flags=0):
  167.         if self._sslobj:
  168.             if flags != 0:
  169.                 raise ValueError(
  170.                     "non-zero flags not allowed in calls to send() on %s" %
  171.                     self.__class__)
  172.             while True:
  173.                 try:
  174.                     v = self._sslobj.write(data)
  175.                 except SSLError, x:
  176.                     if x.args[0] == SSL_ERROR_WANT_READ:
  177.                         return 0
  178.                     elif x.args[0] == SSL_ERROR_WANT_WRITE:
  179.                         return 0
  180.                     else:
  181.                         raise
  182.                 else:
  183.                     return v
  184.         else:
  185.             return self._sock.send(data, flags)
  186.  
  187.     def sendto(self, data, addr, flags=0):
  188.         if self._sslobj:
  189.             raise ValueError("sendto not allowed on instances of %s" %
  190.                              self.__class__)
  191.         else:
  192.             return self._sock.sendto(data, flags, addr)
  193.  
  194.     def sendall(self, data, flags=0):
  195.         if self._sslobj:
  196.             if flags != 0:
  197.                 raise ValueError(
  198.                     "non-zero flags not allowed in calls to sendall() on %s" %
  199.                     self.__class__)
  200.             amount = len(data)
  201.             count = 0
  202.             while (count < amount):
  203.                 v = self.send(data[count:])
  204.                 count += v
  205.             return amount
  206.         else:
  207.             return socket.sendall(self, data, flags)
  208.  
  209.     def recv(self, buflen=1024, flags=0):
  210.         if self._sslobj:
  211.             if flags != 0:
  212.                 raise ValueError(
  213.                     "non-zero flags not allowed in calls to recv() on %s" %
  214.                     self.__class__)
  215.             return self.read(buflen)
  216.         else:
  217.             return self._sock.recv(buflen, flags)
  218.  
  219.     def recv_into(self, buffer, nbytes=None, flags=0):
  220.         if buffer and (nbytes is None):
  221.             nbytes = len(buffer)
  222.         elif nbytes is None:
  223.             nbytes = 1024
  224.         if self._sslobj:
  225.             if flags != 0:
  226.                 raise ValueError(
  227.                   "non-zero flags not allowed in calls to recv_into() on %s" %
  228.                   self.__class__)
  229.             tmp_buffer = self.read(nbytes)
  230.             v = len(tmp_buffer)
  231.             buffer[:v] = tmp_buffer
  232.             return v
  233.         else:
  234.             return self._sock.recv_into(buffer, nbytes, flags)
  235.  
  236.     def recvfrom(self, addr, buflen=1024, flags=0):
  237.         if self._sslobj:
  238.             raise ValueError("recvfrom not allowed on instances of %s" %
  239.                              self.__class__)
  240.         else:
  241.             return self._sock.recvfrom(buflen, flags)
  242.  
  243.     def recvfrom_into(self, buffer, nbytes=None, flags=0):
  244.         if self._sslobj:
  245.             raise ValueError("recvfrom_into not allowed on instances of %s" %
  246.                              self.__class__)
  247.         else:
  248.             return self._sock.recvfrom_into(buffer, nbytes, flags)
  249.  
  250.     def pending(self):
  251.         if self._sslobj:
  252.             return self._sslobj.pending()
  253.         else:
  254.             return 0
  255.  
  256.     def unwrap(self):
  257.         if self._sslobj:
  258.             s = self._sslobj.shutdown()
  259.             self._sslobj = None
  260.             return s
  261.         else:
  262.             raise ValueError("No SSL wrapper around " + str(self))
  263.  
  264.     def shutdown(self, how):
  265.         self._sslobj = None
  266.         socket.shutdown(self, how)
  267.  
  268.     def close(self):
  269.         if self._makefile_refs < 1:
  270.             self._sslobj = None
  271.             socket.close(self)
  272.         else:
  273.             self._makefile_refs -= 1
  274.  
  275.     def do_handshake(self):
  276.  
  277.         """Perform a TLS/SSL handshake."""
  278.  
  279.         self._sslobj.do_handshake()
  280.  
  281.     def connect(self, addr):
  282.  
  283.         """Connects to remote ADDR, and then wraps the connection in
  284.         an SSL channel."""
  285.  
  286.         # Here we assume that the socket is client-side, and not
  287.         # connected at the time of the call.  We connect it, then wrap it.
  288.         if self._sslobj:
  289.             raise ValueError("attempt to connect already-connected SSLSocket!")
  290.         socket.connect(self, addr)
  291.         self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile,
  292.                                     self.cert_reqs, self.ssl_version,
  293.                                     self.ca_certs)
  294.         if self.do_handshake_on_connect:
  295.             self.do_handshake()
  296.  
  297.     def accept(self):
  298.  
  299.         """Accepts a new connection from a remote client, and returns
  300.         a tuple containing that new connection wrapped with a server-side
  301.         SSL channel, and the address of the remote client."""
  302.  
  303.         newsock, addr = socket.accept(self)
  304.         return (SSLSocket(newsock,
  305.                           keyfile=self.keyfile,
  306.                           certfile=self.certfile,
  307.                           server_side=True,
  308.                           cert_reqs=self.cert_reqs,
  309.                           ssl_version=self.ssl_version,
  310.                           ca_certs=self.ca_certs,
  311.                           do_handshake_on_connect=self.do_handshake_on_connect,
  312.                           suppress_ragged_eofs=self.suppress_ragged_eofs),
  313.                 addr)
  314.  
  315.     def makefile(self, mode='r', bufsize=-1):
  316.  
  317.         """Make and return a file-like object that
  318.         works with the SSL connection.  Just use the code
  319.         from the socket module."""
  320.  
  321.         self._makefile_refs += 1
  322.         # close=True so as to decrement the reference count when done with
  323.         # the file-like object.
  324.         return _fileobject(self, mode, bufsize, close=True)
  325.  
  326.  
  327.  
  328. def wrap_socket(sock, keyfile=None, certfile=None,
  329.                 server_side=False, cert_reqs=CERT_NONE,
  330.                 ssl_version=PROTOCOL_SSLv23, ca_certs=None,
  331.                 do_handshake_on_connect=True,
  332.                 suppress_ragged_eofs=True):
  333.  
  334.     return SSLSocket(sock, keyfile=keyfile, certfile=certfile,
  335.                      server_side=server_side, cert_reqs=cert_reqs,
  336.                      ssl_version=ssl_version, ca_certs=ca_certs,
  337.                      do_handshake_on_connect=do_handshake_on_connect,
  338.                      suppress_ragged_eofs=suppress_ragged_eofs)
  339.  
  340.  
  341. # some utility functions
  342.  
  343. def cert_time_to_seconds(cert_time):
  344.  
  345.     """Takes a date-time string in standard ASN1_print form
  346.     ("MON DAY 24HOUR:MINUTE:SEC YEAR TIMEZONE") and return
  347.     a Python time value in seconds past the epoch."""
  348.  
  349.     import time
  350.     return time.mktime(time.strptime(cert_time, "%b %d %H:%M:%S %Y GMT"))
  351.  
  352. PEM_HEADER = "-----BEGIN CERTIFICATE-----"
  353. PEM_FOOTER = "-----END CERTIFICATE-----"
  354.  
  355. def DER_cert_to_PEM_cert(der_cert_bytes):
  356.  
  357.     """Takes a certificate in binary DER format and returns the
  358.     PEM version of it as a string."""
  359.  
  360.     if hasattr(base64, 'standard_b64encode'):
  361.         # preferred because older API gets line-length wrong
  362.         f = base64.standard_b64encode(der_cert_bytes)
  363.         return (PEM_HEADER + '\n' +
  364.                 textwrap.fill(f, 64) + '\n' +
  365.                 PEM_FOOTER + '\n')
  366.     else:
  367.         return (PEM_HEADER + '\n' +
  368.                 base64.encodestring(der_cert_bytes) +
  369.                 PEM_FOOTER + '\n')
  370.  
  371. def PEM_cert_to_DER_cert(pem_cert_string):
  372.  
  373.     """Takes a certificate in ASCII PEM format and returns the
  374.     DER-encoded version of it as a byte sequence"""
  375.  
  376.     if not pem_cert_string.startswith(PEM_HEADER):
  377.         raise ValueError("Invalid PEM encoding; must start with %s"
  378.                          % PEM_HEADER)
  379.     if not pem_cert_string.strip().endswith(PEM_FOOTER):
  380.         raise ValueError("Invalid PEM encoding; must end with %s"
  381.                          % PEM_FOOTER)
  382.     d = pem_cert_string.strip()[len(PEM_HEADER):-len(PEM_FOOTER)]
  383.     return base64.decodestring(d)
  384.  
  385. def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None):
  386.  
  387.     """Retrieve the certificate from the server at the specified address,
  388.     and return it as a PEM-encoded string.
  389.     If 'ca_certs' is specified, validate the server cert against it.
  390.     If 'ssl_version' is specified, use it in the connection attempt."""
  391.  
  392.     host, port = addr
  393.     if (ca_certs is not None):
  394.         cert_reqs = CERT_REQUIRED
  395.     else:
  396.         cert_reqs = CERT_NONE
  397.     s = wrap_socket(socket(), ssl_version=ssl_version,
  398.                     cert_reqs=cert_reqs, ca_certs=ca_certs)
  399.     s.connect(addr)
  400.     dercert = s.getpeercert(True)
  401.     s.close()
  402.     return DER_cert_to_PEM_cert(dercert)
  403.  
  404. def get_protocol_name(protocol_code):
  405.     if protocol_code == PROTOCOL_TLSv1:
  406.         return "TLSv1"
  407.     elif protocol_code == PROTOCOL_SSLv23:
  408.         return "SSLv23"
  409.     elif protocol_code == PROTOCOL_SSLv2:
  410.         return "SSLv2"
  411.     elif protocol_code == PROTOCOL_SSLv3:
  412.         return "SSLv3"
  413.     else:
  414.         return "<unknown>"
  415.  
  416.  
  417. # a replacement for the old socket.ssl function
  418.  
  419. def sslwrap_simple(sock, keyfile=None, certfile=None):
  420.  
  421.     """A replacement for the old socket.ssl function.  Designed
  422.     for compability with Python 2.5 and earlier.  Will disappear in
  423.     Python 3.0."""
  424.  
  425.     if hasattr(sock, "_sock"):
  426.         sock = sock._sock
  427.  
  428.     ssl_sock = _ssl.sslwrap(sock, 0, keyfile, certfile, CERT_NONE,
  429.                             PROTOCOL_SSLv23, None)
  430.     try:
  431.         sock.getpeername()
  432.     except:
  433.         # no, no connection yet
  434.         pass
  435.     else:
  436.         # yes, do the handshake
  437.         ssl_sock.do_handshake()
  438.  
  439.     return ssl_sock
  440.