Пример #1
0
    async def hostnames_to_uris(self, data):
        ret = []
        for h in data['hostname']:
            proto = 'ldaps' if SSL(data['ssl']) == SSL.USESSL else 'ldap'
            parsed = urlparse(f"{proto}://{h}")
            try:
                port = parsed.port
                host = parsed.netloc if not parsed.port else parsed.netloc.rsplit(':', 1)[0]
            except ValueError:
                """
                ParseResult.port will raise a ValueError if the port is not an int
                Ignore for now. ValidationError will be raised in common_validate()
                """
                host, port = h.rsplit(':', 1)

            if port is None:
                port = 636 if SSL(data['ssl']) == SSL.USESSL else 389

            uri = f"{proto}://{host}:{port}"
            ret.append(uri)

        return ret
Пример #2
0
    def _setup_ssl(self, data):
        if SSL(data['security']['ssl']) == SSL.NOSSL:
            return

        cert = data['security']['client_certificate']
        if cert:
            pyldap.set_option(
                pyldap.OPT_X_TLS_CERTFILE,
                f"/etc/certificates/{cert}.crt"
            )
            pyldap.set_option(
                pyldap.OPT_X_TLS_KEYFILE,
                f"/etc/certificates/{cert}.key"
            )

        pyldap.set_option(
            pyldap.OPT_X_TLS_CACERTFILE,
            '/etc/ssl/truenas_cacerts.pem'
        )

        if data['security']['validate_certificates']:
            pyldap.set_option(
                pyldap.OPT_X_TLS_REQUIRE_CERT,
                pyldap.OPT_X_TLS_DEMAND
            )
        else:
            pyldap.set_option(
                pyldap.OPT_X_TLS_REQUIRE_CERT,
                pyldap.OPT_X_TLS_ALLOW
            )

        try:
            pyldap.set_option(pyldap.OPT_X_TLS_NEWCTX, 0)
        except Exception:
            self.logger.warning('Failed to initialize new TLS context.', exc_info=True)

        return
Пример #3
0
    def _open(self):
        """
        We can only intialize a single host. In this case,
        we iterate through a list of hosts until we get one that
        works and then use that to set our LDAP handle.

        SASL GSSAPI bind only succeeds when DNS reverse lookup zone
        is correctly populated. Fall through to simple bind if this
        fails.
        """
        res = None
        if self._isopen:
            return True

        if self.hosts:
            saved_simple_error = None
            saved_gssapi_error = None
            for server in self.hosts:
                try:
                    self._handle = pyldap.initialize(server)
                except Exception as e:
                    self.logger.debug(
                        f'Failed to initialize ldap connection to [{server}]: ({e}). Moving to next server.'
                    )
                    continue

                res = None
                pyldap.protocol_version = pyldap.VERSION3
                pyldap.set_option(pyldap.OPT_REFERRALS, 0)
                pyldap.set_option(pyldap.OPT_NETWORK_TIMEOUT,
                                  self.ldap['dns_timeout'])

                if SSL(self.ldap['ssl']) != SSL.NOSSL:
                    if self.ldap['certificate']:
                        pyldap.set_option(
                            pyldap.OPT_X_TLS_CERTFILE,
                            f"/etc/certificates/{self.ldap['cert_name']}.crt")
                        pyldap.set_option(
                            pyldap.OPT_X_TLS_KEYFILE,
                            f"/etc/certificates/{self.ldap['cert_name']}.key")

                    pyldap.set_option(pyldap.OPT_X_TLS_CACERTFILE,
                                      '/etc/ssl/truenas_cacerts.pem')
                    if self.ldap['validate_certificates']:
                        pyldap.set_option(pyldap.OPT_X_TLS_REQUIRE_CERT,
                                          pyldap.OPT_X_TLS_DEMAND)
                    else:
                        pyldap.set_option(pyldap.OPT_X_TLS_REQUIRE_CERT,
                                          pyldap.OPT_X_TLS_ALLOW)

                    try:
                        pyldap.set_option(pyldap.OPT_X_TLS_NEWCTX, 0)
                    except Exception:
                        self.logger.warning(
                            'Failed to initialize new TLS context.',
                            exc_info=True)

                if SSL(self.ldap['ssl']) == SSL.USESTARTTLS:
                    try:
                        self._handle.start_tls_s()

                    except pyldap.LDAPError as e:
                        self.logger.debug(
                            'Encountered error initializing start_tls: %s', e)
                        saved_simple_error = e
                        continue

                if self.ldap['anonbind']:
                    try:
                        res = self._handle.simple_bind_s()
                        break
                    except Exception as e:
                        saved_simple_error = e
                        self.logger.debug('Anonymous bind failed: %s' % e)
                        continue

                if self.ldap['certificate']:
                    try:
                        res = self._handle.sasl_non_interactive_bind_s(
                            'EXTERNAL')
                        if self.ldap['verbose_logging']:
                            self.logger.debug(
                                'Successfully bound to [%s] using client certificate.',
                                server)
                        break
                    except Exception as e:
                        saved_simple_error = e
                        self.logger.debug('SASL EXTERNAL bind failed.',
                                          exc_info=True)
                        continue

                if self.ldap['kerberos_principal']:
                    try:
                        self._handle.set_option(pyldap.OPT_X_SASL_NOCANON, 1)
                        self._handle.sasl_gssapi_bind_s()
                        res = True
                        break
                    except Exception as e:
                        saved_gssapi_error = e
                        self.logger.debug(
                            f'SASL GSSAPI bind failed: {e}. Attempting simple bind'
                        )

                try:
                    res = self._handle.simple_bind_s(self.ldap['binddn'],
                                                     self.ldap['bindpw'])
                    break
                except Exception as e:
                    self.logger.debug(
                        f'Failed to bind to [{server}] using [{self.ldap["binddn"]}]: {e}'
                    )
                    saved_simple_error = e
                    continue

            if res:
                self._isopen = True

            elif saved_gssapi_error:
                self._convert_exception(saved_gssapi_error)

            elif saved_simple_error:
                self._convert_exception(saved_simple_error)

        return (self._isopen is True)
Пример #4
0
 async def ldap_validate(self, ldap):
     port = 636 if SSL(ldap['ssl']) == SSL.USESSL else 389
     for h in ldap['hostname']:
         await self.middleware.call('ldap.port_is_listening', h, port, ldap['dns_timeout'])
     await self.middleware.call('ldap.validate_credentials')