def _ssl_context_factory(parameters): """ Produce a Twisted SSL context object from a pika connection parameter object. This is necessary as Twisted manages the connection, not Pika. Args: parameters (pika.ConnectionParameters): The connection parameters built from the fedora_messaging configuration. """ client_cert = None ca_cert = None key = config.conf["tls"]["keyfile"] cert = config.conf["tls"]["certfile"] ca_file = config.conf["tls"]["ca_cert"] if ca_file: with open(ca_file, "rb") as fd: # Open it in binary mode since otherwise Twisted will immediately # re-encode it as ASCII, which won't work if the cert bundle has # comments that can't be encoded with ASCII. ca_cert = twisted_ssl.Certificate.loadPEM(fd.read()) if key and cert: # Note that _configure_tls_parameters sets the auth mode to EXTERNAL # if both key and cert are defined, so we don't need to do that here. with open(key) as fd: client_keypair = fd.read() with open(cert) as fd: client_keypair += fd.read() client_cert = twisted_ssl.PrivateCertificate.loadPEM(client_keypair) hostname = parameters.host if not isinstance(hostname, six.text_type): # Twisted requires the hostname as decoded text, which it isn't in Python 2 # Decode with the system encoding since this came from the config file. Die, # Python 2, die. hostname = hostname.decode(locale.getdefaultlocale()[1]) try: context_factory = twisted_ssl.optionsForClientTLS( hostname, trustRoot=ca_cert or twisted_ssl.platformTrust(), clientCertificate=client_cert, extraCertificateOptions={ "raiseMinimumTo": twisted_ssl.TLSVersion.TLSv1_2 }, ) except AttributeError: # Twisted 12.2 path for EL7 :( context_factory = twisted_ssl.CertificateOptions( certificate=client_cert.original, privateKey=client_cert.privateKey.original, caCerts=[ca_cert.original] or twisted_ssl.platformTrust(), verify=True, requireCertificate=True, verifyOnce=False, enableSessions=False, ) return context_factory
def __init__(self, config): self._config = config # Check if we're using a custom list of a CA certificates trust_root = config.federation_ca_trust_root if trust_root is None: # Use CA root certs provided by OpenSSL trust_root = platformTrust() # "insecurelyLowerMinimumTo" is the argument that will go lower than # Twisted's default, which is why it is marked as "insecure" (since # Twisted's defaults are reasonably secure). But, since Twisted is # moving to TLS 1.2 by default, we want to respect the config option if # it is set to 1.0 (which the alternate option, raiseMinimumTo, will not # let us do). minTLS = _TLS_VERSION_MAP[config.federation_client_minimum_tls_version] self._verify_ssl = CertificateOptions(trustRoot=trust_root, insecurelyLowerMinimumTo=minTLS) self._verify_ssl_context = self._verify_ssl.getContext() self._verify_ssl_context.set_info_callback(self._context_info_cb) self._no_verify_ssl = CertificateOptions( insecurelyLowerMinimumTo=minTLS) self._no_verify_ssl_context = self._no_verify_ssl.getContext() self._no_verify_ssl_context.set_info_callback(self._context_info_cb)
def _get_avatar(self, avatarId, mind): endpointstr = self._endpointstr basedn = self._basedn binddn = self._binddn bindpw = self._bindpw query = self._query_template % { 'username': escape_filter_chars(avatarId) } if self._service_based_attribs: if mind: service = mind['service'] else: service = "" if service == "" or service is None or self.service_manager is None: attributes = self._attribs else: service_entry = yield defer.maybeDeferred( self.service_manager.getMatchingService, service) if service_entry and 'attributes' in service_entry: attributes = service_entry['attributes'] else: attributes = self._attribs else: attributes = self._attribs e = clientFromString(reactor, self._endpointstr) client = yield connectProtocol(e, LDAPClient()) startTls = self._startTls startTlsHostName = self._startTlsHostName startTlsAuthority = self._startTlsAuthority if startTls: startTlsArgs = [] if startTlsHostName is not None: if startTlsAuthority is not None: ctx = optionsForClientTLS(unicode(startTlsHostName), startTlsAuthority) else: ctx = optionsForClientTLS(unicode(startTlsHostName), platformTrust()) startTlsArgs.append(ctx) client = yield client.startTLS(*startTlsArgs) yield client.bind(binddn, bindpw) o = ldapsyntax.LDAPEntry(client, basedn) results = yield o.search(filterText=query, attributes=attributes.keys()) yield client.unbind() if len(results) != 1: raise Exception("No unique account found for '%s'." % avatarId) entry = results[0] _attribs = attributes attribs = [] for key, alias in _attribs.iteritems(): if key in entry: valuelist = entry[key] for value in valuelist: attribs.append((alias, value)) user = User(avatarId, attribs) defer.returnValue(user)
def createCertOptions(server): pk = None cert = None if server.cert: pc = PrivateCertificate.loadPEM(open(server.cert,"rb").read()) pk = pc.privateKey.original cert = pc.original tr = platformTrust() if server.verify else None return CertificateOptions(privateKey=pk, certificate=cert, trustRoot=tr)
def creatorForNetloc(self, hostname, port): # trustRoot set to platformTrust() will use the platform's root CAs. # # This means that a website like https://www.cacert.org will be rejected # by default, since CAcert.org CA certificate is seldom shipped. return optionsForClientTLS( hostname=hostname.decode("ascii"), trustRoot=platformTrust(), extraCertificateOptions={'method': self._ssl_method}, )
def creatorForNetloc(self, hostname, port): # trustRoot set to platformTrust() will use the platform's root CAs. # # This means that a website like https://www.cacert.org will be rejected # by default, since CAcert.org CA certificate is seldom shipped. return optionsForClientTLS(hostname.decode("ascii"), trustRoot=platformTrust(), extraCertificateOptions={ 'method': self._ssl_method, })
def __init__(self, config): self._config = config self._options_noverify = CertificateOptions() # Check if we're using a custom list of a CA certificates trust_root = config.federation_ca_trust_root if trust_root is None: # Use CA root certs provided by OpenSSL trust_root = platformTrust() self._options_verify = CertificateOptions(trustRoot=trust_root)
def _get_avatar(self, avatarId, mind): endpointstr = self._endpointstr basedn = self._basedn binddn = self._binddn bindpw = self._bindpw query = self._query_template % {"username": escape_filter_chars(avatarId)} if self._service_based_attribs: if mind: service = mind["service"] else: service = "" if service == "" or service is None or self.service_manager is None: attributes = self._attribs else: service_entry = yield defer.maybeDeferred(self.service_manager.getMatchingService, service) if service_entry and "attributes" in service_entry: attributes = service_entry["attributes"] else: attributes = self._attribs else: attributes = self._attribs e = clientFromString(reactor, self._endpointstr) client = yield connectProtocol(e, LDAPClient()) startTls = self._startTls startTlsHostName = self._startTlsHostName startTlsAuthority = self._startTlsAuthority if startTls: startTlsArgs = [] if startTlsHostName is not None: if startTlsAuthority is not None: ctx = optionsForClientTLS(unicode(startTlsHostName), startTlsAuthority) else: ctx = optionsForClientTLS(unicode(startTlsHostName), platformTrust()) startTlsArgs.append(ctx) client = yield client.startTLS(*startTlsArgs) yield client.bind(binddn, bindpw) o = ldapsyntax.LDAPEntry(client, basedn) results = yield o.search(filterText=query, attributes=attributes.keys()) yield client.unbind() if len(results) != 1: raise Exception("No unique account found for '%s'." % avatarId) entry = results[0] _attribs = attributes attribs = [] for key, alias in _attribs.iteritems(): if key in entry: valuelist = entry[key] for value in valuelist: attribs.append((alias, value)) user = User(avatarId, attribs) defer.returnValue(user)
def __init__(self, config): self._config = config # Check if we're using a custom list of a CA certificates trust_root = config.federation_ca_trust_root if trust_root is None: # Use CA root certs provided by OpenSSL trust_root = platformTrust() self._verify_ssl_context = CertificateOptions( trustRoot=trust_root).getContext() self._verify_ssl_context.set_info_callback(self._context_info_cb) self._no_verify_ssl_context = CertificateOptions().getContext() self._no_verify_ssl_context.set_info_callback(self._context_info_cb)
def __init__(self): # Use CA root certs provided by OpenSSL trust_root = platformTrust() # "insecurelyLowerMinimumTo" is the argument that will go lower than # Twisted's default, which is why it is marked as "insecure" (since # Twisted's defaults are reasonably secure). But, since Twisted is # moving to TLS 1.2 by default, we want to respect the config option if # it is set to 1.0 (which the alternate option, raiseMinimumTo, will not # let us do). minTLS = TLSVersion.TLSv1_2 self._verify_ssl = CertificateOptions(trustRoot=trust_root, insecurelyLowerMinimumTo=minTLS) self._verify_ssl_context = self._verify_ssl.getContext() self._verify_ssl_context.set_info_callback(self._context_info_cb)
def _make_connect(self, credentials): basedn = self._basedn e = clientFromString(reactor, self._endpointstr) client = yield connectProtocol(e, LDAPClient()) startTls = self._startTls startTlsHostName = self._startTlsHostName startTlsAuthority = self._startTlsAuthority if startTls: startTlsArgs = [] if startTlsHostName is not None: if startTlsAuthority is not None: ctx = optionsForClientTLS(unicode(startTlsHostName), startTlsAuthority) else: ctx = optionsForClientTLS(unicode(startTlsHostName), platformTrust()) startTlsArgs.append(ctx) client = yield client.startTLS(*startTlsArgs) dn = yield self._get_dn(client, credentials.username) yield client.bind(dn, credentials.password) yield client.unbind() defer.returnValue(credentials.username)
def main(reactor, host, port=443): contextFactory = ssl.CertificateOptions(trustRoot=ssl.platformTrust()) port = int(port) done = defer.Deferred() class ShowCertificate(protocol.Protocol): def connectionMade(self): self.transport.write(b"GET / HTTP/1.0\r\n\r\n") def dataReceived(self, data): certificate = ssl.Certificate(self.transport.getPeerCertificate()) print(certificate) self.transport.loseConnection() def connectionLost(self, reason): if reason.check(ssl.SSL.Error): print(reason.value) done.callback(None) endpoints.connectProtocol( endpoints.SSL4ClientEndpoint(reactor, host, port, sslContextFactory=contextFactory), ShowCertificate() ) return done
def __init__(self): trust_root = platformTrust() self._ssl_context = CertificateOptions( trustRoot=trust_root).getContext() self._ssl_context.set_info_callback(_context_info_cb)
# OpenSSL mocks SSL.OP_SINGLE_ECDH_USE = 0x00080000 SSL.OP_NO_RENEGOTIATION = 0x40000000 SSL.OP_PRIORITIZE_CHACHA = 0x00200000 TLS_CIPHER_LIST = b'TLS13-AES-256-GCM-SHA384:' \ b'TLS13-AES-128-GCM-SHA256:' \ b'TLS13-CHACHA20-POLY1305-SHA256:' \ b'ECDHE-ECDSA-AES256-GCM-SHA384:' \ b'ECDHE-RSA-AES256-GCM-SHA384:' \ b'ECDHE-ECDSA-AES128-GCM-SHA256:' \ b'ECDHE-RSA-AES128-GCM-SHA256:' \ b'ECDHE-ECDSA-CHACHA20-POLY1305:' \ b'ECDHE-RSA-CHACHA20-POLY1305' trustRoot = ssl.platformTrust() class ValidationException(Exception): pass def gen_ecc_key(bits): key = ec.generate_private_key(ec.SECP256R1(), default_backend()) key = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), )
def run(self, make, start_reactor=True): """ Run the application component. :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession` when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`. :type make: callable :param start_reactor: if True (the default) this method starts the Twisted reactor and doesn't return until the reactor stops. If there are any problems starting the reactor or connect()-ing, we stop the reactor and raise the exception back to the caller. :returns: None is returned, unless you specify ``start_reactor=False`` in which case the Deferred that connect() returns is returned; this will callback() with an IProtocol instance, which will actually be an instance of :class:`WampWebSocketClientProtocol` """ from twisted.internet import reactor txaio.use_twisted() txaio.config.loop = reactor isSecure, host, port, resource, path, params = parseWsUrl(self.url) # start logging to console if self.debug or self.debug_wamp or self.debug_app: log.startLogging(sys.stdout) # factory for use ApplicationSession def create(): cfg = ComponentConfig(self.realm, self.extra) try: session = make(cfg) except Exception as e: if start_reactor: # the app component could not be created .. fatal log.err(str(e)) reactor.stop() else: # if we didn't start the reactor, it's up to the # caller to deal with errors raise else: session.debug_app = self.debug_app return session # create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory(create, url=self.url, debug=self.debug, debug_wamp=self.debug_wamp) # if user passed ssl= but isn't using isSecure, we'll never # use the ssl argument which makes no sense. context_factory = None if self.ssl is not None: if not isSecure: raise RuntimeError( 'ssl= argument value passed to %s conflicts with the "ws:" ' 'prefix of the url argument. Did you mean to use "wss:"?' % self.__class__.__name__) context_factory = self.ssl elif isSecure: from twisted.internet.ssl import platformTrust context_factory = platformTrust() if isSecure: from twisted.internet.endpoints import SSL4ClientEndpoint assert context_factory is not None client = SSL4ClientEndpoint(reactor, host, port, context_factory) else: from twisted.internet.endpoints import TCP4ClientEndpoint client = TCP4ClientEndpoint(reactor, host, port) d = client.connect(transport_factory) # if the user didn't ask us to start the reactor, then they # get to deal with any connect errors themselves. if start_reactor: # if an error happens in the connect(), we save the underlying # exception so that after the event-loop exits we can re-raise # it to the caller. class ErrorCollector(object): exception = None def __call__(self, failure): self.exception = failure.value # print(failure.getErrorMessage()) reactor.stop() connect_error = ErrorCollector() d.addErrback(connect_error) # now enter the Twisted reactor loop reactor.run() # if we exited due to a connection error, raise that to the # caller if connect_error.exception: raise connect_error.exception else: # let the caller handle any errors return d
def __init__(self, config): verify_requests = config.getboolean("http", "federation.verifycerts") if verify_requests: self._options = ssl.CertificateOptions(trustRoot=ssl.platformTrust()) else: self._options = ssl.CertificateOptions()
def __init__(self, verify_requests: bool): if verify_requests: self._options = ssl.CertificateOptions( trustRoot=ssl.platformTrust()) else: self._options = ssl.CertificateOptions()