_ssl2.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. # Wrapper module for _ssl. Written by Bill Janssen.
  2. # Ported to gevent by Denis Bilenko.
  3. """SSL wrapper for socket objects on Python 2.7.8 and below.
  4. For the documentation, refer to :mod:`ssl` module manual.
  5. This module implements cooperative SSL socket wrappers.
  6. """
  7. from __future__ import absolute_import
  8. # Our import magic sadly makes this warning useless
  9. # pylint: disable=undefined-variable,arguments-differ,no-member
  10. import ssl as __ssl__
  11. _ssl = __ssl__._ssl
  12. import sys
  13. import errno
  14. from gevent._socket2 import socket
  15. from gevent.socket import _fileobject, timeout_default
  16. from gevent.socket import error as socket_error, EWOULDBLOCK
  17. from gevent.socket import timeout as _socket_timeout
  18. from gevent._compat import PYPY
  19. from gevent._util import copy_globals
  20. __implements__ = ['SSLSocket',
  21. 'wrap_socket',
  22. 'get_server_certificate',
  23. 'sslwrap_simple']
  24. # Import all symbols from Python's ssl.py, except those that we are implementing
  25. # and "private" symbols.
  26. __imports__ = copy_globals(__ssl__, globals(),
  27. # SSLSocket *must* subclass gevent.socket.socket; see issue 597
  28. names_to_ignore=__implements__ + ['socket'],
  29. dunder_names_to_keep=())
  30. # Py2.6 can get RAND_status added twice
  31. __all__ = list(set(__implements__) | set(__imports__))
  32. if 'namedtuple' in __all__:
  33. __all__.remove('namedtuple')
  34. class SSLSocket(socket):
  35. """
  36. gevent `ssl.SSLSocket <https://docs.python.org/2.6/library/ssl.html#sslsocket-objects>`_
  37. for Pythons < 2.7.9.
  38. """
  39. def __init__(self, sock, keyfile=None, certfile=None,
  40. server_side=False, cert_reqs=CERT_NONE,
  41. ssl_version=PROTOCOL_SSLv23, ca_certs=None,
  42. do_handshake_on_connect=True,
  43. suppress_ragged_eofs=True,
  44. ciphers=None):
  45. socket.__init__(self, _sock=sock)
  46. if PYPY:
  47. sock._drop()
  48. if certfile and not keyfile:
  49. keyfile = certfile
  50. # see if it's connected
  51. try:
  52. socket.getpeername(self)
  53. except socket_error as e:
  54. if e.args[0] != errno.ENOTCONN:
  55. raise
  56. # no, no connection yet
  57. self._sslobj = None
  58. else:
  59. # yes, create the SSL object
  60. if ciphers is None:
  61. self._sslobj = _ssl.sslwrap(self._sock, server_side,
  62. keyfile, certfile,
  63. cert_reqs, ssl_version, ca_certs)
  64. else:
  65. self._sslobj = _ssl.sslwrap(self._sock, server_side,
  66. keyfile, certfile,
  67. cert_reqs, ssl_version, ca_certs,
  68. ciphers)
  69. if do_handshake_on_connect:
  70. self.do_handshake()
  71. self.keyfile = keyfile
  72. self.certfile = certfile
  73. self.cert_reqs = cert_reqs
  74. self.ssl_version = ssl_version
  75. self.ca_certs = ca_certs
  76. self.ciphers = ciphers
  77. self.do_handshake_on_connect = do_handshake_on_connect
  78. self.suppress_ragged_eofs = suppress_ragged_eofs
  79. self._makefile_refs = 0
  80. def read(self, len=1024):
  81. """Read up to LEN bytes and return them.
  82. Return zero-length string on EOF."""
  83. while True:
  84. try:
  85. return self._sslobj.read(len)
  86. except SSLError as ex:
  87. if ex.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
  88. return ''
  89. elif ex.args[0] == SSL_ERROR_WANT_READ:
  90. if self.timeout == 0.0:
  91. raise
  92. sys.exc_clear()
  93. self._wait(self._read_event, timeout_exc=_SSLErrorReadTimeout)
  94. elif ex.args[0] == SSL_ERROR_WANT_WRITE:
  95. if self.timeout == 0.0:
  96. raise
  97. sys.exc_clear()
  98. # note: using _SSLErrorReadTimeout rather than _SSLErrorWriteTimeout below is intentional
  99. self._wait(self._write_event, timeout_exc=_SSLErrorReadTimeout)
  100. else:
  101. raise
  102. def write(self, data):
  103. """Write DATA to the underlying SSL channel. Returns
  104. number of bytes of DATA actually transmitted."""
  105. while True:
  106. try:
  107. return self._sslobj.write(data)
  108. except SSLError as ex:
  109. if ex.args[0] == SSL_ERROR_WANT_READ:
  110. if self.timeout == 0.0:
  111. raise
  112. sys.exc_clear()
  113. self._wait(self._read_event, timeout_exc=_SSLErrorWriteTimeout)
  114. elif ex.args[0] == SSL_ERROR_WANT_WRITE:
  115. if self.timeout == 0.0:
  116. raise
  117. sys.exc_clear()
  118. self._wait(self._write_event, timeout_exc=_SSLErrorWriteTimeout)
  119. else:
  120. raise
  121. def getpeercert(self, binary_form=False):
  122. """Returns a formatted version of the data in the
  123. certificate provided by the other end of the SSL channel.
  124. Return None if no certificate was provided, {} if a
  125. certificate was provided, but not validated."""
  126. return self._sslobj.peer_certificate(binary_form)
  127. def cipher(self):
  128. if not self._sslobj:
  129. return None
  130. return self._sslobj.cipher()
  131. def send(self, data, flags=0, timeout=timeout_default):
  132. if timeout is timeout_default:
  133. timeout = self.timeout
  134. if self._sslobj:
  135. if flags != 0:
  136. raise ValueError(
  137. "non-zero flags not allowed in calls to send() on %s" %
  138. self.__class__)
  139. while True:
  140. try:
  141. v = self._sslobj.write(data)
  142. except SSLError as x:
  143. if x.args[0] == SSL_ERROR_WANT_READ:
  144. if self.timeout == 0.0:
  145. return 0
  146. sys.exc_clear()
  147. self._wait(self._read_event)
  148. elif x.args[0] == SSL_ERROR_WANT_WRITE:
  149. if self.timeout == 0.0:
  150. return 0
  151. sys.exc_clear()
  152. self._wait(self._write_event)
  153. else:
  154. raise
  155. else:
  156. return v
  157. else:
  158. return socket.send(self, data, flags, timeout)
  159. # is it possible for sendall() to send some data without encryption if another end shut down SSL?
  160. def sendall(self, data, flags=0):
  161. try:
  162. socket.sendall(self, data)
  163. except _socket_timeout as ex:
  164. if self.timeout == 0.0:
  165. # Python 2 simply *hangs* in this case, which is bad, but
  166. # Python 3 raises SSLWantWriteError. We do the same.
  167. raise SSLError(SSL_ERROR_WANT_WRITE)
  168. # Convert the socket.timeout back to the sslerror
  169. raise SSLError(*ex.args)
  170. def sendto(self, *args):
  171. if self._sslobj:
  172. raise ValueError("sendto not allowed on instances of %s" %
  173. self.__class__)
  174. else:
  175. return socket.sendto(self, *args)
  176. def recv(self, buflen=1024, flags=0):
  177. if self._sslobj:
  178. if flags != 0:
  179. raise ValueError(
  180. "non-zero flags not allowed in calls to recv() on %s" %
  181. self.__class__)
  182. # QQQ Shouldn't we wrap the SSL_WANT_READ errors as socket.timeout errors to match socket.recv's behavior?
  183. return self.read(buflen)
  184. else:
  185. return socket.recv(self, buflen, flags)
  186. def recv_into(self, buffer, nbytes=None, flags=0):
  187. if buffer and (nbytes is None):
  188. nbytes = len(buffer)
  189. elif nbytes is None:
  190. nbytes = 1024
  191. if self._sslobj:
  192. if flags != 0:
  193. raise ValueError(
  194. "non-zero flags not allowed in calls to recv_into() on %s" %
  195. self.__class__)
  196. while True:
  197. try:
  198. tmp_buffer = self.read(nbytes)
  199. v = len(tmp_buffer)
  200. buffer[:v] = tmp_buffer
  201. return v
  202. except SSLError as x:
  203. if x.args[0] == SSL_ERROR_WANT_READ:
  204. if self.timeout == 0.0:
  205. raise
  206. sys.exc_clear()
  207. self._wait(self._read_event)
  208. continue
  209. else:
  210. raise
  211. else:
  212. return socket.recv_into(self, buffer, nbytes, flags)
  213. def recvfrom(self, *args):
  214. if self._sslobj:
  215. raise ValueError("recvfrom not allowed on instances of %s" %
  216. self.__class__)
  217. else:
  218. return socket.recvfrom(self, *args)
  219. def recvfrom_into(self, *args):
  220. if self._sslobj:
  221. raise ValueError("recvfrom_into not allowed on instances of %s" %
  222. self.__class__)
  223. else:
  224. return socket.recvfrom_into(self, *args)
  225. def pending(self):
  226. if self._sslobj:
  227. return self._sslobj.pending()
  228. return 0
  229. def _sslobj_shutdown(self):
  230. while True:
  231. try:
  232. return self._sslobj.shutdown()
  233. except SSLError as ex:
  234. if ex.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
  235. return ''
  236. elif ex.args[0] == SSL_ERROR_WANT_READ:
  237. if self.timeout == 0.0:
  238. raise
  239. sys.exc_clear()
  240. self._wait(self._read_event, timeout_exc=_SSLErrorReadTimeout)
  241. elif ex.args[0] == SSL_ERROR_WANT_WRITE:
  242. if self.timeout == 0.0:
  243. raise
  244. sys.exc_clear()
  245. self._wait(self._write_event, timeout_exc=_SSLErrorWriteTimeout)
  246. else:
  247. raise
  248. def unwrap(self):
  249. if self._sslobj:
  250. s = self._sslobj_shutdown()
  251. self._sslobj = None
  252. return socket(_sock=s)
  253. else:
  254. raise ValueError("No SSL wrapper around " + str(self))
  255. def shutdown(self, how):
  256. self._sslobj = None
  257. socket.shutdown(self, how)
  258. def close(self):
  259. if self._makefile_refs < 1:
  260. self._sslobj = None
  261. socket.close(self)
  262. else:
  263. self._makefile_refs -= 1
  264. if PYPY:
  265. def _reuse(self):
  266. self._makefile_refs += 1
  267. def _drop(self):
  268. if self._makefile_refs < 1:
  269. self.close()
  270. else:
  271. self._makefile_refs -= 1
  272. def do_handshake(self):
  273. """Perform a TLS/SSL handshake."""
  274. while True:
  275. try:
  276. return self._sslobj.do_handshake()
  277. except SSLError as ex:
  278. if ex.args[0] == SSL_ERROR_WANT_READ:
  279. if self.timeout == 0.0:
  280. raise
  281. sys.exc_clear()
  282. self._wait(self._read_event, timeout_exc=_SSLErrorHandshakeTimeout)
  283. elif ex.args[0] == SSL_ERROR_WANT_WRITE:
  284. if self.timeout == 0.0:
  285. raise
  286. sys.exc_clear()
  287. self._wait(self._write_event, timeout_exc=_SSLErrorHandshakeTimeout)
  288. else:
  289. raise
  290. def connect(self, addr):
  291. """Connects to remote ADDR, and then wraps the connection in
  292. an SSL channel."""
  293. # Here we assume that the socket is client-side, and not
  294. # connected at the time of the call. We connect it, then wrap it.
  295. if self._sslobj:
  296. raise ValueError("attempt to connect already-connected SSLSocket!")
  297. socket.connect(self, addr)
  298. if self.ciphers is None:
  299. self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile,
  300. self.cert_reqs, self.ssl_version,
  301. self.ca_certs)
  302. else:
  303. self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile,
  304. self.cert_reqs, self.ssl_version,
  305. self.ca_certs, self.ciphers)
  306. if self.do_handshake_on_connect:
  307. self.do_handshake()
  308. def accept(self):
  309. """Accepts a new connection from a remote client, and returns
  310. a tuple containing that new connection wrapped with a server-side
  311. SSL channel, and the address of the remote client."""
  312. sock = self._sock
  313. while True:
  314. try:
  315. client_socket, address = sock.accept()
  316. break
  317. except socket_error as ex:
  318. if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
  319. raise
  320. sys.exc_clear()
  321. self._wait(self._read_event)
  322. sslobj = SSLSocket(client_socket,
  323. keyfile=self.keyfile,
  324. certfile=self.certfile,
  325. server_side=True,
  326. cert_reqs=self.cert_reqs,
  327. ssl_version=self.ssl_version,
  328. ca_certs=self.ca_certs,
  329. do_handshake_on_connect=self.do_handshake_on_connect,
  330. suppress_ragged_eofs=self.suppress_ragged_eofs,
  331. ciphers=self.ciphers)
  332. return sslobj, address
  333. def makefile(self, mode='r', bufsize=-1):
  334. """Make and return a file-like object that
  335. works with the SSL connection. Just use the code
  336. from the socket module."""
  337. if not PYPY:
  338. self._makefile_refs += 1
  339. # close=True so as to decrement the reference count when done with
  340. # the file-like object.
  341. return _fileobject(self, mode, bufsize, close=True)
  342. if PYPY or not hasattr(SSLSocket, 'timeout'):
  343. # PyPy (and certain versions of CPython) doesn't have a direct
  344. # 'timeout' property on raw sockets, because that's not part of
  345. # the documented specification. We may wind up wrapping a raw
  346. # socket (when ssl is used with PyWSGI) or a gevent socket, which
  347. # does have a read/write timeout property as an alias for
  348. # get/settimeout, so make sure that's always the case because
  349. # pywsgi can depend on that.
  350. SSLSocket.timeout = property(lambda self: self.gettimeout(),
  351. lambda self, value: self.settimeout(value))
  352. _SSLErrorReadTimeout = SSLError('The read operation timed out')
  353. _SSLErrorWriteTimeout = SSLError('The write operation timed out')
  354. _SSLErrorHandshakeTimeout = SSLError('The handshake operation timed out')
  355. def wrap_socket(sock, keyfile=None, certfile=None,
  356. server_side=False, cert_reqs=CERT_NONE,
  357. ssl_version=PROTOCOL_SSLv23, ca_certs=None,
  358. do_handshake_on_connect=True,
  359. suppress_ragged_eofs=True, ciphers=None):
  360. """Create a new :class:`SSLSocket` instance."""
  361. return SSLSocket(sock, keyfile=keyfile, certfile=certfile,
  362. server_side=server_side, cert_reqs=cert_reqs,
  363. ssl_version=ssl_version, ca_certs=ca_certs,
  364. do_handshake_on_connect=do_handshake_on_connect,
  365. suppress_ragged_eofs=suppress_ragged_eofs,
  366. ciphers=ciphers)
  367. def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None):
  368. """Retrieve the certificate from the server at the specified address,
  369. and return it as a PEM-encoded string.
  370. If 'ca_certs' is specified, validate the server cert against it.
  371. If 'ssl_version' is specified, use it in the connection attempt."""
  372. if ca_certs is not None:
  373. cert_reqs = CERT_REQUIRED
  374. else:
  375. cert_reqs = CERT_NONE
  376. s = wrap_socket(socket(), ssl_version=ssl_version,
  377. cert_reqs=cert_reqs, ca_certs=ca_certs)
  378. s.connect(addr)
  379. dercert = s.getpeercert(True)
  380. s.close()
  381. return DER_cert_to_PEM_cert(dercert)
  382. def sslwrap_simple(sock, keyfile=None, certfile=None):
  383. """A replacement for the old socket.ssl function. Designed
  384. for compatability with Python 2.5 and earlier. Will disappear in
  385. Python 3.0."""
  386. return SSLSocket(sock, keyfile, certfile)