Skip to content

Commit e3f5fb2

Browse files
gregarndtglandium
authored andcommitted
Bug 1269367 - Create socket connection to IP address. r=glandium
Socket connections can be made to an IP address instead of a hostname, but httplib connections should maintain the hostname in self.host for SSL certificate validation.
1 parent 155c926 commit e3f5fb2

File tree

1 file changed

+25
-13
lines changed

1 file changed

+25
-13
lines changed

storage.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import errno
88
import httplib
99
import os
10+
import socket
1011
import time
1112
import urllib2
1213

@@ -271,23 +272,34 @@ def ConnectionWrapperFactory(parent_class, dns_query):
271272
method uses the dns_query function to resolve the connection host name.
272273
'''
273274
class ConnectionWrapper(parent_class):
274-
def connect(self):
275+
def create_connection(self, address, timeout, source_address):
276+
'''
277+
httplib.HTTP(S)Connection creates a socket connection to
278+
self.host using _create_connection, which by default is a
279+
redirect to socket.create_connection(). self._create_connection exists
280+
on httplib.HTTPConnection as a way of overriding it for unit tests.
281+
Connections are made to self.host by default. When attempting
282+
to perform DNS resolution and connecting to an IP address instead
283+
of hostname, SSL certificate validation is broken in Python 2.7.9+.
284+
This wrapper allows for a dns query to be made, and socket
285+
connection made to an IP address while still maintaining self.host
286+
as the unresolved hostname for validation.
287+
'''
275288
t0 = time.time()
276-
# httplib uses self.host both as the host to connect to and as the
277-
# Host header, because boto doesn't set that. As it happens,
278-
# httplib sets the Host header before this method is called, so
279-
# we can change self.host for use when opening the socket. However,
280-
# boto reuses HTTP(S)Connection instances, and on the next request,
281-
# httplib resets the Host header with self.host, so we need to
282-
# restore it.
283-
host = self.host
284-
self.host = dns_query(self.host)
285-
t1 = time.time()
289+
host, port = address
290+
resolvedHost = dns_query(host)
291+
self._socket_connect_timestamp = t1 = time.time()
286292
_last_stats['dns'] = (t1 - t0) * 1000
293+
sock = socket.create_connection((resolvedHost, port),
294+
timeout, source_address)
295+
return sock
296+
297+
def connect(self):
298+
self._create_connection = self.create_connection
287299
parent_class.connect(self)
288-
self.host = host
289300
self._connect_time = time.time()
290-
_last_stats['connect'] = (self._connect_time - t1) * 1000
301+
_last_stats['connect'] = (
302+
self._connect_time - self._socket_connect_timestamp) * 1000
291303

292304
def getresponse(self, buffering=False):
293305
res = parent_class.getresponse(self, buffering)

0 commit comments

Comments
 (0)