1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import socket
21 from qpid.util import connect
22
23 TRANSPORTS = {}
24
26
28 self.socket = connect(host, port)
29 if conn.tcp_nodelay:
30 self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
31
33 return self.socket.fileno()
34
35 -class tcp(SocketTransport):
36
39
42
43 - def send(self, bytes):
44 return self.socket.send(bytes)
45
47 return self.socket.recv(n)
48
51
52 TRANSPORTS["tcp"] = tcp
53
54 try:
55 from ssl import wrap_socket, SSLError, SSL_ERROR_WANT_READ, \
56 SSL_ERROR_WANT_WRITE, CERT_REQUIRED, CERT_NONE
57 except ImportError:
58
59
60 from socket import ssl
61
64 SocketTransport.__init__(self, conn, host, port)
65
66
67
68 ssl_keyfile = conn.ssl_keyfile
69 ssl_certfile = conn.ssl_certfile
70 if ssl_certfile and not ssl_keyfile:
71 ssl_keyfile = ssl_certfile
72
73
74
75
76
77
78 if conn.ssl_trustfile:
79 raise socket.error("This version of Python does not support verification of the peer's certificate.")
80
81 self.ssl = ssl(self.socket, keyfile=ssl_keyfile, certfile=ssl_certfile)
82 self.socket.setblocking(1)
83
86
89
91 return self.ssl.read(n)
92
94 return self.ssl.write(s)
95
98
99 TRANSPORTS["ssl"] = old_ssl
100 TRANSPORTS["tcp+tls"] = old_ssl
101
102 else:
103 - class tls(SocketTransport):
104
106 SocketTransport.__init__(self, conn, host, port)
107 if conn.ssl_trustfile:
108 validate = CERT_REQUIRED
109 else:
110 validate = CERT_NONE
111
112
113 actual = getattr(conn, "_ssl_skip_hostname_check_actual", None)
114 if actual is not None and conn.ssl_skip_hostname_check is False:
115 validate = CERT_REQUIRED
116
117 self.tls = wrap_socket(self.socket, keyfile=conn.ssl_keyfile,
118 certfile=conn.ssl_certfile,
119 ca_certs=conn.ssl_trustfile,
120 cert_reqs=validate)
121
122 if validate == CERT_REQUIRED and not conn.ssl_skip_hostname_check:
123 verify_hostname(self.tls.getpeercert(), host)
124
125 self.socket.setblocking(0)
126 self.state = None
127
128
129
130 self.write_retry = None
131
133 if self.state is None:
134 return reading
135 else:
136 return self.state == SSL_ERROR_WANT_READ
137
139 if self.state is None:
140 return writing
141 else:
142 return self.state == SSL_ERROR_WANT_WRITE
143
144 - def send(self, bytes):
145 if self.write_retry is None:
146 self.write_retry = bytes
147 self._clear_state()
148 try:
149 n = self.tls.write( self.write_retry )
150 self.write_retry = None
151 return n
152 except SSLError, e:
153 if self._update_state(e.args[0]):
154
155 return 0
156 self.write_retry = None
157 raise
158 except:
159 self.write_retry = None
160 raise
161
163 self._clear_state()
164 try:
165 return self.tls.read(n)
166 except SSLError, e:
167 if self._update_state(e.args[0]):
168
169 return None
170 else:
171 raise
172
175
177 if code in (SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE):
178 self.state = code
179 return True
180 else:
181 return False
182
184 self.socket.setblocking(1)
185
186 self.tls.close()
187
189 match_found = False
190 peer_names = []
191 if peer_certificate:
192 if 'subjectAltName' in peer_certificate:
193 for san in peer_certificate['subjectAltName']:
194 if san[0] == 'DNS':
195 peer_names.append(san[1].lower())
196 if 'subject' in peer_certificate:
197 for sub in peer_certificate['subject']:
198 while isinstance(sub, tuple) and isinstance(sub[0], tuple):
199 sub = sub[0]
200 if sub[0] == 'commonName':
201 peer_names.append(sub[1].lower())
202 for pattern in peer_names:
203 if _match_dns_pattern(hostname.lower(), pattern):
204 match_found = True
205 break
206 if not match_found:
207 raise SSLError("Connection hostname '%s' does not match names from peer certificate: %s" % (hostname, peer_names))
208
210 """ For checking the hostnames provided by the peer's certificate
211 """
212 if pattern.find("*") == -1:
213 return hostname == pattern
214
215
216 h_labels = hostname.split(".")
217 p_labels = pattern.split(".")
218
219 while h_labels and p_labels:
220 if p_labels[0].find("*") == -1:
221 if p_labels[0] != h_labels[0]:
222 return False
223 else:
224 p = p_labels[0].split("*")
225 if not h_labels[0].startswith(p[0]):
226 return False
227 if not h_labels[0].endswith(p[1]):
228 return False
229 h_labels.pop(0)
230 p_labels.pop(0)
231
232 return not h_labels and not p_labels
233
234
235 TRANSPORTS["ssl"] = tls
236 TRANSPORTS["tcp+tls"] = tls
237