def _validate_tls_ciphersuites()

in mysqlx-connector-python/lib/mysqlx/connection.py [0:0]


def _validate_tls_ciphersuites(settings: Dict[str, Any]) -> None:
    """Validate tls-ciphersuites.

    Args:
        settings (dict): Settings dictionary.

    Raises:
        :class:`mysqlx.InterfaceError`: If tls-ciphersuites name is not valid.
    """
    tls_ciphersuites = []
    if "tls-ciphersuites" not in settings:
        return

    tls_ciphersuites_settings = settings["tls-ciphersuites"]

    if isinstance(tls_ciphersuites_settings, str):
        if not (
            tls_ciphersuites_settings.startswith("[")
            and tls_ciphersuites_settings.endswith("]")
        ):
            raise InterfaceError(
                "tls-ciphersuites must be a list, found: "
                f"'{tls_ciphersuites_settings}'"
            )
        tls_css = tls_ciphersuites_settings[1:-1].split(",")
        if not tls_css:
            raise InterfaceError(
                "No valid cipher suite found in the 'tls-ciphersuites' list"
            )
        for tls_cs in tls_css:
            tls_cs = tls_cs.strip().upper()
            if tls_cs:
                tls_ciphersuites.append(tls_cs)
    elif isinstance(tls_ciphersuites_settings, (list, set)):
        tls_ciphersuites = [tls_cs for tls_cs in tls_ciphersuites_settings if tls_cs]
    else:
        raise InterfaceError(
            "tls-ciphersuites should be a list with one or more ciphersuites. "
            f"Found: '{tls_ciphersuites_settings}'"
        )

    tls_versions = (
        SUPPORTED_TLS_VERSIONS[:]
        if settings.get("tls-versions", None) is None
        else settings["tls-versions"][:]
    )

    # A newer TLS version can use a cipher introduced on
    # an older version.
    tls_versions.sort(reverse=True)
    newer_tls_ver = tls_versions[0]

    translated_names = []
    iani_cipher_suites_names = {}
    ossl_cipher_suites_names: List[str] = []

    # Old ciphers can work with new TLS versions.
    # Find all the ciphers introduced on previous TLS versions
    for tls_ver in SUPPORTED_TLS_VERSIONS[
        : SUPPORTED_TLS_VERSIONS.index(newer_tls_ver) + 1
    ]:
        iani_cipher_suites_names.update(TLS_CIPHER_SUITES[tls_ver])
        ossl_cipher_suites_names.extend(OPENSSL_CS_NAMES[tls_ver])

    for name in tls_ciphersuites:
        if "-" in name and name in ossl_cipher_suites_names:
            translated_names.append(name)
        elif name in iani_cipher_suites_names:
            translated_name = iani_cipher_suites_names[name]
            if translated_name in translated_names:
                raise AttributeError(
                    DUPLICATED_IN_LIST_ERROR.format(
                        list="tls_ciphersuites", value=translated_name
                    )
                )
            translated_names.append(translated_name)
        else:
            raise InterfaceError(
                f"The value '{name}' in cipher suites is not a valid cipher suite"
            )

    if not translated_names:
        raise InterfaceError(
            "No valid cipher suite found in the 'tls-ciphersuites' list"
        )

    # raise an error when using an unacceptable cipher
    for cipher_as_ossl in translated_names:
        for tls_ver in SUPPORTED_TLS_VERSIONS[
            : SUPPORTED_TLS_VERSIONS.index(newer_tls_ver) + 1
        ]:
            if (
                cipher_as_ossl
                in UNACCEPTABLE_TLS_CIPHERSUITES.get(tls_ver, {}).values()
            ):
                raise NotSupportedError(
                    f"Cipher {cipher_as_ossl} when used with {tls_ver} is unacceptable."
                )

    settings["tls-ciphersuites"] = translated_names