def list_templates(self, kwargs):
        """
        List certificate templates.
        Arguments:
            @enabled:bool
                Results will only show enabled templates
            @verbose:bool
                Results will contain full information
        """
        verbose = kwargs.get("verbose", False)
        enabled = kwargs.get("enabled", False)

        self.engine.set_controls(LDAP_SERVER_SD_FLAGS_OID_SEC_DESC)
        if verbose:
            attributes = self.engine.all_attributes()
        else:
            attributes = [
                "name",
                "displayName",
                "pKIExpirationPeriod",
                "msPKI-Certificate-Name-Flag",
                "msPKI-Enrollment-Flag",
                "pKIExtendedKeyUsage",
                "msPKI-Template-Schema-Version",
                "nTSecurityDescriptor",
            ]

        templates = self.engine.query(
            self.engine.TEMPLATE_FILTER(),
            attributes,
            base=",".join(
                [
                    "CN=Certificate Templates,CN=Public Key Services,CN=Services",
                    self.engine.ldap.server.info.other["configurationNamingContext"][0],
                ]
            ),
        )

        attributes = ["certificateTemplates", "cn"]
        pkis_infos = self.engine.query(
            self.engine.PKI_FILTER(),
            attributes,
            base=",".join(
                [
                    "CN=Enrollment Services,CN=Public Key Services,CN=Services",
                    self.engine.ldap.server.info.other["configurationNamingContext"][0],
                ]
            ),
        )
        self.engine.set_controls()

        adcs_infos = {}
        for pki in pkis_infos:
            adcs_infos[pki.get("cn")] = pki.get("certificateTemplates")

        if verbose:
            self.display(templates, verbose)
            return
        else:
            all_enabled_templates = list(set().union(*adcs_infos.values()))
            template_number = 1
            for template in templates:
                if enabled and template.get("name") not in all_enabled_templates:
                    continue

                print(template_number)
                print(f"{'Template Name':<30}: {template.get('name')}")
                print(f"{'Display Name':<30}: {template.get('displayName')}")

                is_enabled = False
                cert_authorities = []
                for ca in adcs_infos:
                    if template.get("name") in adcs_infos[ca]:
                        is_enabled = True
                        cert_authorities.append(ca)

                if is_enabled:
                    print(f"{'Certificate Authority':<30}: {cert_authorities[0]}")
                    for cert_auth in cert_authorities[1:]:
                        print(f"{' ' * 32}{cert_auth}")
                    print(f"{'Enabled':<30}: True")
                else:
                    print(f"{'Enabled':<30}: False")

                ekus = []
                client_auth = False
                if "pKIExtendedKeyUsage" in template.keys():
                    for eku in template.get("pKIExtendedKeyUsage"):
                        if eku in AUTHENTICATING_EKUS.keys():
                            client_auth = True
                        try:
                            ekus.append(OID_TO_STR_MAP[eku])
                        except KeyError:
                            ekus.append(eku)
                    if template.get("pKIExtendedKeyUsage") == []:
                        client_auth = True
                else:
                    client_auth = True
                print(f"{'Client Authentication':<30}: {client_auth}")

                flag_mask = template.get("msPKI-Certificate-Name-Flag") & 0xFFFFFFFF
                flags = []
                for flag_name, flag_value in MS_PKI_CERTIFICATE_NAME_FLAG.items():
                    if flag_mask & flag_value:
                        flags.append(flag_name)
                print(
                    f"{'Enrollee Supplies Subject':<30}: {'ENROLLEE_SUPPLIES_SUBJECT' in flags}"
                )
                manager_approval = (
                    template.get("msPKI-Enrollment-Flag")
                    & MS_PKI_ENROLLMENT_FLAG["PEND_ALL_REQUESTS"]
                )
                print(f"{'Requires Manager Approval':<30}: {manager_approval>0}")

                print(
                    f"{'Template Schema Version':<30}: {template.get('msPKI-Template-Schema-Version','')}"
                )

                if ekus:
                    print(f"{'Extended Key Usage':<30}: {ekus[0]}")
                    for eku in ekus[1:]:
                        print(f"{' ' * 32}{eku}")
                else:
                    print(f"{'Any Purpose':<30}: True")

                # Enrollment Rights
                enroll_principals = []
                full_control_principals = []
                write_owner_principals = []
                write_dacl_principals = []
                write_property_principals = []
                for principal in (
                    template.get("nTSecurityDescriptor").get("DACL").get("ACEs")
                ):
                    right = ""
                    sid = principal.get("SID")
                    try:
                        res = self.engine.resolve_sid(sid)
                        if isinstance(res, str):
                            name = res
                        else:
                            res = next(res)
                            if "group" in res["objectClass"]:
                                name = f"{res['sAMAccountName']}"
                            elif "user" in res["objectClass"]:
                                name = f"{res['sAMAccountName']}"
                            elif "computer" in res["objectClass"]:
                                name = res["dNSHostName"]
                            else:
                                # foreignSecurityPrincipal maybe other things ?
                                pass
                    except:
                        # we can't resolve the sid (delete or from another domain)
                        name = sid

                    # extended rights
                    mask = principal.get("Raw Access Required")
                    if principal.get("GUID"):
                        right = principal.get("GUID").lower().strip("{}")
                        if right and mask & ADRights.get(
                            "ExtendedRight"
                        ) == ADRights.get("ExtendedRight"):
                            if (
                                right == EXTENDED_RIGHTS_NAME_MAP["Enroll"]
                                or right
                                == EXTENDED_RIGHTS_NAME_MAP["All-Extended-Rights"]
                            ):
                                enroll_principals.append(name)

                    # Object Control Permissions
                    if mask & ADRights.get("GenericAll") == ADRights.get("GenericAll"):
                        full_control_principals.append(name)
                    if mask & ADRights.get("WriteOwner") == ADRights.get("WriteOwner"):
                        write_owner_principals.append(name)
                    if mask & ADRights.get("WriteDacl") == ADRights.get("WriteDacl"):
                        write_dacl_principals.append(name)
                    if mask & ADRights.get("WriteProperty") == ADRights.get(
                        "WriteProperty"
                    ):
                        if (
                            right != "0e10c968-78fb-11d2-90d4-00c04f79dc55"
                            and right != "a05b8cc2-17bc-4802-a710-e7c15ab866a2"
                        ):
                            if (
                                right
                                and right != "00000000-0000-0000-0000-000000000000"
                            ):
                                self.engine.create_objecttype_guid_map()
                                if right in self.engine.objecttype_guid_map.values():
                                    guid_to_object_map = {
                                        k: v
                                        for v, k in self.engine.objecttype_guid_map.items()
                                    }
                                    right = guid_to_object_map[right]
                                write_property_principals.append(f"{name} on {right}")
                            else:
                                write_property_principals.append(name)

                print("Permissions")
                if enroll_principals:
                    print("  Enrollment Permissions")
                    print(f"{'    Enrollment Rights':<30}: {enroll_principals[0]}")
                    for enroll_principal in enroll_principals[1:]:
                        print(f"{' ' * 32}{enroll_principal}")

                # Object Control Permissions
                print("  Object Control Permissions")
                owner_sid = template.get("nTSecurityDescriptor").get("Owner SID")
                try:
                    res = next(self.engine.resolve_sid(owner_sid))
                    if "group" in res["objectClass"]:
                        name = f"{res['sAMAccountName']} (group)"
                    elif "user" in res["objectClass"]:
                        name = f"{res['sAMAccountName']}"
                    elif "computer" in res["objectClass"]:
                        name = res["dNSHostName"]
                    else:
                        # foreignSecurityPrincipal maybe other things ?
                        pass
                except:
                    # we can't resolve the sid (delete or from another domain)
                    name = owner_sid

                print(f"{'    Owner':<30}: {name}")
                if full_control_principals:
                    # FIXME TODO
                    print(
                        f"{'    Full Control Principals':<30}: {full_control_principals[0]}"
                    )
                if write_owner_principals:
                    print(
                        f"{'    Write Owner Principals':<30}: {write_owner_principals[0]}"
                    )
                    for write_owner_principal in write_owner_principals[1:]:
                        print(f"{' ' * 32}{write_owner_principal}")

                if write_dacl_principals:
                    print(
                        f"{'    Write Dacl Principals':<30}: {write_dacl_principals[0]}"
                    )
                    for write_dacl_principal in write_dacl_principals[1:]:
                        print(f"{' ' * 32}{write_dacl_principal}")

                if write_property_principals:
                    print(
                        f"{'    Write Property Principals':<30}: {write_property_principals[0]}"
                    )
                    for write_property_principal in write_property_principals[1:]:
                        print(f"{' ' * 32}{write_property_principal}")

                print()
                template_number += 1

        List certificate templates.
        Arguments:
            @enabled:bool
                Results will only show enabled templates
            @verbose:bool
                Results will contain full information
        
ldeep/__main__.py