Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: swarm_client/third_party/requests/packages/urllib3/contrib/pyopenssl.py

Issue 69143004: Delete swarm_client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 '''SSL with SNI-support for Python 2.
2
3 This needs the following packages installed:
4
5 * pyOpenSSL (tested with 0.13)
6 * ndg-httpsclient (tested with 0.3.2)
7 * pyasn1 (tested with 0.1.6)
8
9 To activate it call :func:`~urllib3.contrib.pyopenssl.inject_into_urllib3`.
10 This can be done in a ``sitecustomize`` module, or at any other time before
11 your application begins using ``urllib3``, like this::
12
13 try:
14 import urllib3.contrib.pyopenssl
15 urllib3.contrib.pyopenssl.inject_into_urllib3()
16 except ImportError:
17 pass
18
19 Now you can use :mod:`urllib3` as you normally would, and it will support SNI
20 when the required modules are installed.
21 '''
22
23 from ndg.httpsclient.ssl_peer_verification import SUBJ_ALT_NAME_SUPPORT
24 from ndg.httpsclient.subj_alt_name import SubjectAltName
25 import OpenSSL.SSL
26 from pyasn1.codec.der import decoder as der_decoder
27 from socket import _fileobject
28 import ssl
29 from cStringIO import StringIO
30
31 from .. import connectionpool
32 from .. import util
33
34 __all__ = ['inject_into_urllib3', 'extract_from_urllib3']
35
36 # SNI only *really* works if we can read the subjectAltName of certificates.
37 HAS_SNI = SUBJ_ALT_NAME_SUPPORT
38
39 # Map from urllib3 to PyOpenSSL compatible parameter-values.
40 _openssl_versions = {
41 ssl.PROTOCOL_SSLv23: OpenSSL.SSL.SSLv23_METHOD,
42 ssl.PROTOCOL_SSLv3: OpenSSL.SSL.SSLv3_METHOD,
43 ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD,
44 }
45 _openssl_verify = {
46 ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE,
47 ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER,
48 ssl.CERT_REQUIRED: OpenSSL.SSL.VERIFY_PEER
49 + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
50 }
51
52
53 orig_util_HAS_SNI = util.HAS_SNI
54 orig_connectionpool_ssl_wrap_socket = connectionpool.ssl_wrap_socket
55
56
57 def inject_into_urllib3():
58 'Monkey-patch urllib3 with PyOpenSSL-backed SSL-support.'
59
60 connectionpool.ssl_wrap_socket = ssl_wrap_socket
61 util.HAS_SNI = HAS_SNI
62
63
64 def extract_from_urllib3():
65 'Undo monkey-patching by :func:`inject_into_urllib3`.'
66
67 connectionpool.ssl_wrap_socket = orig_connectionpool_ssl_wrap_socket
68 util.HAS_SNI = orig_util_HAS_SNI
69
70
71 ### Note: This is a slightly bug-fixed version of same from ndg-httpsclient.
72 def get_subj_alt_name(peer_cert):
73 # Search through extensions
74 dns_name = []
75 if not SUBJ_ALT_NAME_SUPPORT:
76 return dns_name
77
78 general_names = SubjectAltName()
79 for i in range(peer_cert.get_extension_count()):
80 ext = peer_cert.get_extension(i)
81 ext_name = ext.get_short_name()
82 if ext_name != 'subjectAltName':
83 continue
84
85 # PyOpenSSL returns extension data in ASN.1 encoded form
86 ext_dat = ext.get_data()
87 decoded_dat = der_decoder.decode(ext_dat,
88 asn1Spec=general_names)
89
90 for name in decoded_dat:
91 if not isinstance(name, SubjectAltName):
92 continue
93 for entry in range(len(name)):
94 component = name.getComponentByPosition(entry)
95 if component.getName() != 'dNSName':
96 continue
97 dns_name.append(str(component.getComponent()))
98
99 return dns_name
100
101
102 class fileobject(_fileobject):
103
104 def read(self, size=-1):
105 # Use max, disallow tiny reads in a loop as they are very inefficient.
106 # We never leave read() with any leftover data from a new recv() call
107 # in our internal buffer.
108 rbufsize = max(self._rbufsize, self.default_bufsize)
109 # Our use of StringIO rather than lists of string objects returned by
110 # recv() minimizes memory usage and fragmentation that occurs when
111 # rbufsize is large compared to the typical return value of recv().
112 buf = self._rbuf
113 buf.seek(0, 2) # seek end
114 if size < 0:
115 # Read until EOF
116 self._rbuf = StringIO() # reset _rbuf. we consume it via buf.
117 while True:
118 try:
119 data = self._sock.recv(rbufsize)
120 except OpenSSL.SSL.WantReadError:
121 continue
122 if not data:
123 break
124 buf.write(data)
125 return buf.getvalue()
126 else:
127 # Read until size bytes or EOF seen, whichever comes first
128 buf_len = buf.tell()
129 if buf_len >= size:
130 # Already have size bytes in our buffer? Extract and return.
131 buf.seek(0)
132 rv = buf.read(size)
133 self._rbuf = StringIO()
134 self._rbuf.write(buf.read())
135 return rv
136
137 self._rbuf = StringIO() # reset _rbuf. we consume it via buf.
138 while True:
139 left = size - buf_len
140 # recv() will malloc the amount of memory given as its
141 # parameter even though it often returns much less data
142 # than that. The returned data string is short lived
143 # as we copy it into a StringIO and free it. This avoids
144 # fragmentation issues on many platforms.
145 try:
146 data = self._sock.recv(left)
147 except OpenSSL.SSL.WantReadError:
148 continue
149 if not data:
150 break
151 n = len(data)
152 if n == size and not buf_len:
153 # Shortcut. Avoid buffer data copies when:
154 # - We have no data in our buffer.
155 # AND
156 # - Our call to recv returned exactly the
157 # number of bytes we were asked to read.
158 return data
159 if n == left:
160 buf.write(data)
161 del data # explicit free
162 break
163 assert n <= left, "recv(%d) returned %d bytes" % (left, n)
164 buf.write(data)
165 buf_len += n
166 del data # explicit free
167 #assert buf_len == buf.tell()
168 return buf.getvalue()
169
170 def readline(self, size=-1):
171 buf = self._rbuf
172 buf.seek(0, 2) # seek end
173 if buf.tell() > 0:
174 # check if we already have it in our buffer
175 buf.seek(0)
176 bline = buf.readline(size)
177 if bline.endswith('\n') or len(bline) == size:
178 self._rbuf = StringIO()
179 self._rbuf.write(buf.read())
180 return bline
181 del bline
182 if size < 0:
183 # Read until \n or EOF, whichever comes first
184 if self._rbufsize <= 1:
185 # Speed up unbuffered case
186 buf.seek(0)
187 buffers = [buf.read()]
188 self._rbuf = StringIO() # reset _rbuf. we consume it via buf.
189 data = None
190 recv = self._sock.recv
191 while True:
192 try:
193 while data != "\n":
194 data = recv(1)
195 if not data:
196 break
197 buffers.append(data)
198 except OpenSSL.SSL.WantReadError:
199 continue
200 break
201 return "".join(buffers)
202
203 buf.seek(0, 2) # seek end
204 self._rbuf = StringIO() # reset _rbuf. we consume it via buf.
205 while True:
206 try:
207 data = self._sock.recv(self._rbufsize)
208 except OpenSSL.SSL.WantReadError:
209 continue
210 if not data:
211 break
212 nl = data.find('\n')
213 if nl >= 0:
214 nl += 1
215 buf.write(data[:nl])
216 self._rbuf.write(data[nl:])
217 del data
218 break
219 buf.write(data)
220 return buf.getvalue()
221 else:
222 # Read until size bytes or \n or EOF seen, whichever comes first
223 buf.seek(0, 2) # seek end
224 buf_len = buf.tell()
225 if buf_len >= size:
226 buf.seek(0)
227 rv = buf.read(size)
228 self._rbuf = StringIO()
229 self._rbuf.write(buf.read())
230 return rv
231 self._rbuf = StringIO() # reset _rbuf. we consume it via buf.
232 while True:
233 try:
234 data = self._sock.recv(self._rbufsize)
235 except OpenSSL.SSL.WantReadError:
236 continue
237 if not data:
238 break
239 left = size - buf_len
240 # did we just receive a newline?
241 nl = data.find('\n', 0, left)
242 if nl >= 0:
243 nl += 1
244 # save the excess data to _rbuf
245 self._rbuf.write(data[nl:])
246 if buf_len:
247 buf.write(data[:nl])
248 break
249 else:
250 # Shortcut. Avoid data copy through buf when returning
251 # a substring of our first recv().
252 return data[:nl]
253 n = len(data)
254 if n == size and not buf_len:
255 # Shortcut. Avoid data copy through buf when
256 # returning exactly all of our first recv().
257 return data
258 if n >= left:
259 buf.write(data[:left])
260 self._rbuf.write(data[left:])
261 break
262 buf.write(data)
263 buf_len += n
264 #assert buf_len == buf.tell()
265 return buf.getvalue()
266
267
268 class WrappedSocket(object):
269 '''API-compatibility wrapper for Python OpenSSL's Connection-class.'''
270
271 def __init__(self, connection, socket):
272 self.connection = connection
273 self.socket = socket
274
275 def fileno(self):
276 return self.socket.fileno()
277
278 def makefile(self, mode, bufsize=-1):
279 return fileobject(self.connection, mode, bufsize)
280
281 def settimeout(self, timeout):
282 return self.socket.settimeout(timeout)
283
284 def sendall(self, data):
285 return self.connection.sendall(data)
286
287 def close(self):
288 return self.connection.shutdown()
289
290 def getpeercert(self, binary_form=False):
291 x509 = self.connection.get_peer_certificate()
292
293 if not x509:
294 return x509
295
296 if binary_form:
297 return OpenSSL.crypto.dump_certificate(
298 OpenSSL.crypto.FILETYPE_ASN1,
299 x509)
300
301 return {
302 'subject': (
303 (('commonName', x509.get_subject().CN),),
304 ),
305 'subjectAltName': [
306 ('DNS', value)
307 for value in get_subj_alt_name(x509)
308 ]
309 }
310
311
312 def _verify_callback(cnx, x509, err_no, err_depth, return_code):
313 return err_no == 0
314
315
316 def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
317 ca_certs=None, server_hostname=None,
318 ssl_version=None):
319 ctx = OpenSSL.SSL.Context(_openssl_versions[ssl_version])
320 if certfile:
321 ctx.use_certificate_file(certfile)
322 if keyfile:
323 ctx.use_privatekey_file(keyfile)
324 if cert_reqs != ssl.CERT_NONE:
325 ctx.set_verify(_openssl_verify[cert_reqs], _verify_callback)
326 if ca_certs:
327 try:
328 ctx.load_verify_locations(ca_certs, None)
329 except OpenSSL.SSL.Error as e:
330 raise ssl.SSLError('bad ca_certs: %r' % ca_certs, e)
331
332 cnx = OpenSSL.SSL.Connection(ctx, sock)
333 cnx.set_tlsext_host_name(server_hostname)
334 cnx.set_connect_state()
335 while True:
336 try:
337 cnx.do_handshake()
338 except OpenSSL.SSL.WantReadError:
339 continue
340 except OpenSSL.SSL.Error as e:
341 raise ssl.SSLError('bad handshake', e)
342 break
343
344 return WrappedSocket(cnx, sock)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698