1# 2# Licensed to the Apache Software Foundation (ASF) under one 3# or more contributor license agreements. See the NOTICE file 4# distributed with this work for additional information 5# regarding copyright ownership. The ASF licenses this file 6# to you under the Apache License, Version 2.0 (the 7# "License"); you may not use this file except in compliance 8# with the License. You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, 13# software distributed under the License is distributed on an 14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15# KIND, either express or implied. See the License for the 16# specific language governing permissions and limitations 17# under the License. 18# 19 20importsocket 21fromqpid.utilimportconnect 22 23TRANSPORTS={} 24

64SocketTransport.__init__(self,conn,host,port) 65# Bug (QPID-4337): this is the "old" version of python SSL. 66# The private key is required. If a certificate is given, but no 67# keyfile, assume the key is contained in the certificate 68ssl_keyfile=conn.ssl_keyfile 69ssl_certfile=conn.ssl_certfile 70ifssl_certfileandnotssl_keyfile: 71ssl_keyfile=ssl_certfile 72 73# this version of SSL does NOT perform certificate validation. If the 74# connection has been configured with CA certs (via ssl_trustfile), then 75# the application expects the certificate to be validated against the 76# supplied CA certs. Since this version cannot validate, the peer cannot 77# be trusted. 78ifconn.ssl_trustfile: 79raisesocket.error("This version of Python does not support verification of the peer's certificate.") 80 81self.ssl=ssl(self.socket,keyfile=ssl_keyfile,certfile=ssl_certfile) 82self.socket.setblocking(1)

106SocketTransport.__init__(self,conn,host,port)107ifconn.ssl_trustfile:108validate=CERT_REQUIRED109else:110validate=CERT_NONE111112self.tls=wrap_socket(self.socket,keyfile=conn.ssl_keyfile,113certfile=conn.ssl_certfile,114ca_certs=conn.ssl_trustfile,115cert_reqs=validate)116117ifvalidate==CERT_REQUIREDandnotconn.ssl_skip_hostname_check:118match_found=False119peer_cert=self.tls.getpeercert()120ifpeer_cert:121peer_names=[]122if'subjectAltName'inpeer_cert:123forsaninpeer_cert['subjectAltName']:124ifsan[0]=='DNS':125peer_names.append(san[1].lower())126if'subject'inpeer_cert:127forsubinpeer_cert['subject']:128whileisinstance(sub,tuple)andisinstance(sub[0],tuple):129sub=sub[0]# why the extra level of indirection???130ifsub[0]=='commonName':131peer_names.append(sub[1].lower())132forpatterninpeer_names:133if_match_dns_pattern(host.lower(),pattern):134#print "Match found %s" % pattern135match_found=True136break137ifnotmatch_found:138raiseSSLError("Connection hostname '%s' does not match names from peer certificate: %s"%(host,peer_names))139140self.socket.setblocking(0)141self.state=None142# See qpid-4872: need to store the parameters last passed to143# tls.recv_into() and tls.write() in case the calls fail with an144# SSL_ERROR_WANT_* error and we have to retry the call.145self.write_retry=None# buffer passed to last call of tls.write()146self.read_retry=None# buffer passed to last call of tls.recv_into()

161ifself.write_retryisNone:162self.write_retry=bytes163self._clear_state()164try:165n=self.tls.write(self.write_retry)166self.write_retry=None167returnn168exceptSSLError,e:169ifself._update_state(e.args[0]):170# will retry on next invokation171return0172self.write_retry=None173raise174except:175self.write_retry=None176raise

179ifself.read_retry==None:180self.read_retry=bytearray(n)181self._clear_state()182try:183n=self.tls.recv_into(self.read_retry)184r=str(self.read_retry[:n])185self.read_retry=None186returnr187exceptSSLError,e:188ifself._update_state(e.args[0]):189# will retry on next invokation190returnNone191self.read_retry=None192raise193except:194self.read_retry=None195raise