Example #1
0
class Idmap_DomainToBackend(Model):
    idmap_dtb_domain = models.OneToOneField(
        Idmap_Domain,
        on_delete=models.deletion.CASCADE,
        to_field='idmap_domain_name',
        unique=True, null=True,
        verbose_name=_('pre-Windows 2000 Domain Name'),
    )
    idmap_dtb_idmap_backend = models.CharField(
        choices=choices.IDMAP_CHOICES(),
        default='rid',
        max_length=120,
        verbose_name=_("idmap backend for domain"),
    )
Example #2
0
class LDAP(DirectoryServiceBase):
    ldap_hostname = models.CharField(
        verbose_name=_("Hostname"),
        max_length=120,
        help_text=_("The name or IP address of the LDAP server"),
        blank=True
    )
    ldap_basedn = models.CharField(
        verbose_name=_("Base DN"),
        max_length=120,
        help_text=_(
            "The default base Distinguished Name (DN) to use for "
            "searches, eg dc=test,dc=org"),
        blank=True
    )
    ldap_binddn = models.CharField(
        verbose_name=_("Bind DN"),
        max_length=256,
        help_text=_(
            "The distinguished name with which to bind to the "
            "directory server, e.g. cn=admin,dc=test,dc=org"),
        blank=True
    )
    ldap_bindpw = models.CharField(
        verbose_name=_("Bind password"),
        max_length=120,
        help_text=_("The credentials with which to bind."),
        blank=True
    )
    ldap_anonbind = models.BooleanField(
        verbose_name=_("Allow Anonymous Binding"),
        default=False
    )
    ldap_usersuffix = models.CharField(
        verbose_name=_("User Suffix"),
        max_length=120,
        help_text=_(
            "This parameter specifies the suffix that is used for "
            "users when these are added to the LDAP directory, e.g. "
            "ou=Users"),
        blank=True
    )
    ldap_groupsuffix = models.CharField(
        verbose_name=_("Group Suffix"),
        max_length=120,
        help_text=_(
            "This parameter specifies the suffix that is used "
            "for groups when these are added to the LDAP directory, e.g. "
            "ou=Groups"),
        blank=True
    )
    ldap_passwordsuffix = models.CharField(
        verbose_name=_("Password Suffix"),
        max_length=120,
        help_text=_(
            "This parameter specifies the suffix that is used for "
            "passwords when these are added to the LDAP directory, e.g. "
            "ou=Passwords"),
        blank=True
    )
    ldap_machinesuffix = models.CharField(
        verbose_name=_("Machine Suffix"),
        max_length=120,
        help_text=_(
            "This parameter specifies the suffix that is used for "
            "machines when these are added to the LDAP directory, e.g. "
            "ou=Computers"),
        blank=True
    )
    ldap_sudosuffix = models.CharField(
        verbose_name=_("SUDO Suffix"),
        max_length=120,
        help_text=_(
            "This parameter specifies the suffix that is used for "
            "the SUDO configuration in the LDAP directory, e.g. "
            "ou=SUDOers"),
        blank=True
    )
    ldap_kerberos_realm = models.ForeignKey(
        KerberosRealm,
        verbose_name=_("Kerberos Realm"),
        on_delete=models.SET_NULL,
        blank=True,
        null=True
    )
    ldap_kerberos_principal = models.CharField(
        verbose_name=_("Kerberos Princpal"),
        max_length=255,
        blank=True
    )
    ldap_ssl = models.CharField(
        verbose_name=_("Encryption Mode"),
        max_length=120,
        help_text=_(
            "This parameter specifies whether to use SSL/TLS, e.g."
            " on/off/start_tls"
        ),
        choices=choices.LDAP_SSL_CHOICES,
        default='off'
    )
    ldap_certificate = models.ForeignKey(
        Certificate,
        verbose_name=_("Certificate"),
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        limit_choices_to={'cert_certificate__isnull': False, 'cert_privatekey__isnull': False}
    )
    ldap_timeout = models.IntegerField(
        verbose_name=_("LDAP timeout"),
        help_text=_("Timeout for LDAP related commands."),
        default=10
    )
    ldap_dns_timeout = models.IntegerField(
        verbose_name=_("DNS timeout"),
        help_text=_("Timeout for LDAP DNS queries."),
        default=10
    )
    ldap_idmap_backend = models.CharField(
        verbose_name=_("Idmap Backend"),
        choices=choices.IDMAP_CHOICES(),
        max_length=120,
        help_text=_("Idmap backend for winbind."),
        default=enum_to_idmap(IDMAP_TYPE_LDAP)
    )
    ldap_has_samba_schema = models.BooleanField(
        verbose_name=_("Samba Schema"),
        default=False
    )
    ldap_auxiliary_parameters = models.TextField(
        verbose_name=_("Auxiliary Parameters"),
        blank=True,
        help_text=_("These parameters are added to nslcd.conf")
    )
    ldap_schema = models.CharField(
        verbose_name=("Schema"),
        choices=choices.LDAP_SCHEMA_CHOICES,
        max_length=120,
        help_text=_("LDAP Schema type."),
        default=choices.LDAP_SCHEMA_CHOICES[0][0]
    )
    ldap_enable = models.BooleanField(
        verbose_name=_("Enable"),
        default=False
    )

    def __init__(self, *args, **kwargs):
        super(LDAP, self).__init__(*args, **kwargs)

        if self.ldap_bindpw:
            try:
                self.ldap_bindpw = notifier().pwenc_decrypt(self.ldap_bindpw)
            except Exception:
                log.debug(
                    'Failed to decrypt LDAP bind password',
                    exc_info=True
                )
                self.ldap_bindpw = ''
        self._ldap_bindpw_encrypted = False

        self.ds_type = DS_TYPE_LDAP
        self.ds_name = enum_to_directoryservice(self.ds_type)

    def save(self, *args, **kwargs):
        if self.ldap_bindpw and not self._ldap_bindpw_encrypted:
            self.ldap_bindpw = notifier().pwenc_encrypt(
                self.ldap_bindpw
            )
            self._ldap_bindpw_encrypted = True
        super(LDAP, self).save(*args, **kwargs)

    class Meta:
        verbose_name = _("LDAP")
        verbose_name_plural = _("LDAP")
Example #3
0
class ActiveDirectory(DirectoryServiceBase):
    ad_domainname = models.CharField(
        verbose_name=_("Domain Name (DNS/Realm-Name)"),
        max_length=120,
        help_text=_("Domain Name, eg example.com")
    )
    ad_bindname = models.CharField(
        verbose_name=_("Domain Account Name"),
        max_length=120,
        help_text=_("Domain account name to bind as"),
        blank=True
    )
    ad_bindpw = models.CharField(
        verbose_name=_("Domain Account Password"),
        max_length=120,
        help_text=_("Domain Account password."),
        blank=True
    )
    ad_ssl = models.CharField(
        verbose_name=_("Encryption Mode"),
        max_length=120,
        help_text=_(
            "This parameter specifies whether to use SSL/TLS, e.g."
            " on/off/start_tls"
        ),
        choices=choices.LDAP_SSL_CHOICES,
        default='off'
    )
    ad_certificate = models.ForeignKey(
        Certificate,
        verbose_name=_("Certificate"),
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        limit_choices_to={'cert_certificate__isnull': False, 'cert_privatekey__isnull': False}
    )
    ad_verbose_logging = models.BooleanField(
        verbose_name=_("Verbose logging"),
        default=False
    )
    ad_unix_extensions = models.BooleanField(
        verbose_name=_("UNIX extensions"),
        help_text=_("Set this if your Active Directory has UNIX extensions."),
        default=False
    )
    ad_allow_trusted_doms = models.BooleanField(
        verbose_name=_("Allow Trusted Domains"),
        help_text=_("Set this if you want to allow Trusted Domains."),
        default=False
    )
    ad_use_default_domain = models.BooleanField(
        verbose_name=_("Use Default Domain"),
        help_text=_(
            "Set this if you want to use the default "
            "domain for users and groups."),
        default=False
    )
    ad_allow_dns_updates = models.BooleanField(
        verbose_name=_("Allow DNS updates"),
        help_text=_("Set this if you want to allow allow DNS updates."),
        default=True
    )
    ad_disable_freenas_cache = models.BooleanField(
        verbose_name=_("Disable Active Directory user/group cache"),
        help_text=_(
            "Set this if you want to disable caching Active Directory users "
            "and groups. Use this option if you are experiencing slowness or "
            "having difficulty binding to the domain with a large number of "
            "users and groups."),
        default=False
    )
    ad_site = models.CharField(
        verbose_name=_("Site Name"),
        max_length=120,
        help_text=_(
            "Name of Active Directory Site. This field will be automatically populated "
            "during the domain join process. If an AD site is not configured for the "
            "subnet where the NAS is located, the site name will be populated as "
            "'Default-First-Site-Name'"),
        blank=True,
        null=True
    )
    ad_kerberos_realm = models.ForeignKey(
        KerberosRealm,
        verbose_name=_("Kerberos Realm"),
        on_delete=models.SET_NULL,
        blank=True,
        null=True
    )
    ad_kerberos_principal = models.CharField(
        verbose_name=_("Kerberos Princpal"),
        max_length=255,
        help_text=_(
            "Kerberos principal to use for AD-related UI and middleware operations "
            "Field is populated with principals present in the system keytab. "
            "During the domain join process a keytab entry is generated for the "
            "AD Machine Account associated with the NAS. The name for this account "
            "is the netbios name of the server with a '$' appended to it. Once "
            "the NAS is joined to active directory, the bind credentials will be "
            "automatically cleared and all future operations carried out by the AD "
            "machine account, which has a restricted set of privileges in the AD domain."),
        blank=True,
	null=True
    )
    ad_createcomputer = models.CharField(
        blank=True,
        max_length=255,
        verbose_name=_('Computer Account OU'),
        help_text=(
            'If blank, then the default OU is used during computer account creation. '
            'Precreate the computer account in a specific OU. The OU string '
            'read from top to bottom without RDNs and delimited by a "/". '
            'E.g. "createcomputer=Computers/Servers/Unix NB: A backslash '
            '"\" is used as escape at multiple levels and may need to be '
            'doubled or even quadrupled. It is not used as a separator.'
        )
    )
    ad_timeout = models.IntegerField(
        verbose_name=_("AD timeout"),
        help_text=_("Timeout for AD related commands."),
        default=60
    )
    ad_dns_timeout = models.IntegerField(
        verbose_name=_("DNS timeout"),
        help_text=_("Timeout for AD DNS queries."),
        default=60
    )
    ad_idmap_backend = models.CharField(
        verbose_name=_("Idmap backend"),
        choices=choices.IDMAP_CHOICES(),
        max_length=120,
        help_text=_("Idmap backend for winbind."),
        default=enum_to_idmap(IDMAP_TYPE_RID)
    )
    ad_nss_info = models.CharField(
        max_length=120,
        blank=True,
        null=True,
        choices=choices.NSS_INFO_CHOICES,
        verbose_name=_("Winbind NSS Info"),
        help_text=_("This parameter is designed to control how Winbind "
                    "retrieves Name Service Information to construct a user's "
                    "home directory and login")
    )
    ad_ldap_sasl_wrapping = models.CharField(
        verbose_name=_("SASL wrapping"),
        choices=choices.LDAP_SASL_WRAPPING_CHOICES,
        max_length=120,
        help_text=_("The client ldap sasl wrapping defines whether ldap "
                    "traffic will be signed or signed and encrypted (sealed)."
                    "This option is needed in the case of Domain Controllers "
                    "enforcing the usage of signed LDAP connections (e.g. "
                    "Windows 2000 SP3 or higher). LDAP sign and seal can be "
                    "controlled with the registry key \"HKLM\System\\"
                    "CurrentControlSet\\Services\\NTDS\\Parameters\\"
                    "LDAPServerIntegrity\" on the Windows server side."
                    ),
        default='plain'
    )
    ad_enable = models.BooleanField(
        verbose_name=_("Enable"),
        default=False
    )

    def __init__(self, *args, **kwargs):
        super(ActiveDirectory, self).__init__(*args, **kwargs)

        if self.ad_bindpw:
            try:
                self.ad_bindpw = notifier().pwenc_decrypt(self.ad_bindpw)
            except Exception:
                log.debug('Failed to decrypt AD bind password', exc_info=True)
                self.ad_bindpw = ''
        self._ad_bindpw_encrypted = False

        self.ds_type = DS_TYPE_ACTIVEDIRECTORY
        self.ds_name = enum_to_directoryservice(self.ds_type)

    def save(self, **kwargs):
        if self.ad_bindpw and not self._ad_bindpw_encrypted:
            self.ad_bindpw = notifier().pwenc_encrypt(
                self.ad_bindpw
            )
            self._ad_bindpw_encrypted = True
        super(ActiveDirectory, self).save(**kwargs)

    class Meta:
        verbose_name = _("Active Directory")
        verbose_name_plural = _("Active Directory")
Example #4
0
class ActiveDirectory(DirectoryServiceBase):
    ad_domainname = models.CharField(
        verbose_name=_("Domain Name (DNS/Realm-Name)"),
        max_length=120,
        help_text=_("Domain Name, eg example.com")
    )
    ad_bindname = models.CharField(
        verbose_name=_("Domain Account Name"),
        max_length=120,
        help_text=_("Domain account name to bind as"),
        blank=True
    )
    ad_bindpw = models.CharField(
        verbose_name=_("Domain Account Password"),
        max_length=120,
        help_text=_("Domain Account password."),
        blank=True
    )
    ad_monitor_frequency = models.IntegerField(
        verbose_name=_("AD check connectivity frequency (seconds)"),
        default=60,
        validators=[MaxValueValidator(3600), MinValueValidator(30)],
        help_text=_("How often to verify that AD servers are active."),
        blank=False
    )
    ad_recover_retry = models.IntegerField(
        verbose_name=_("How many recovery attempts"),
        default=10,
        validators=[MaxValueValidator(500), MinValueValidator(0)],
        help_text=_(
            "Number of times to attempt to recover the connection with AD "
            "server. If the value is 0, try forever."),
        blank=False
    )
    ad_enable_monitor = models.BooleanField(
        verbose_name=_("Enable Monitoring"),
        help_text=_("Restart AD automatically if the service is disconnected."),
        default=False
    )
    ad_ssl = models.CharField(
        verbose_name=_("Encryption Mode"),
        max_length=120,
        help_text=_(
            "This parameter specifies whether to use SSL/TLS, e.g."
            " on/off/start_tls"
        ),
        choices=choices.LDAP_SSL_CHOICES,
        default='off'
    )
    ad_certificate = models.ForeignKey(
        Certificate,
        verbose_name=_("Certificate"),
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        limit_choices_to={'cert_certificate__isnull': False, 'cert_privatekey__isnull': False}
    )
    ad_verbose_logging = models.BooleanField(
        verbose_name=_("Verbose logging"),
        default=False
    )
    ad_unix_extensions = models.BooleanField(
        verbose_name=_("UNIX extensions"),
        help_text=_("Set this if your Active Directory has UNIX extensions."),
        default=False
    )
    ad_allow_trusted_doms = models.BooleanField(
        verbose_name=_("Allow Trusted Domains"),
        help_text=_("Set this if you want to allow Trusted Domains."),
        default=False
    )
    ad_use_default_domain = models.BooleanField(
        verbose_name=_("Use Default Domain"),
        help_text=_(
            "Set this if you want to use the default "
            "domain for users and groups."),
        default=False
    )
    ad_allow_dns_updates = models.BooleanField(
        verbose_name=_("Allow DNS updates"),
        help_text=_("Set this if you want to allow allow DNS updates."),
        default=True
    )
    ad_disable_freenas_cache = models.BooleanField(
        verbose_name=_("Disable Active Directory user/group cache"),
        help_text=_(
            "Set this if you want to disable caching Active Directory users "
            "and groups. Use this option if you are experiencing slowness or "
            "having difficulty binding to the domain with a large number of "
            "users and groups."),
        default=False
    )
    ad_userdn = models.CharField(
        verbose_name=_("User Base"),
        max_length=1024,
        help_text=_("DN of the user container in AD."),
        blank=True,
        null=True
    )
    ad_groupdn = models.CharField(
        verbose_name=_("Group Base"),
        max_length=1024,
        help_text=_("DN of the group container in AD."),
        blank=True,
        null=True
    )
    ad_site = models.CharField(
        verbose_name=_("Site Name"),
        max_length=120,
        help_text=_("Name of site to use."),
        blank=True,
        null=True
    )
    ad_dcname = models.CharField(
        verbose_name=_("Domain Controller"),
        max_length=120,
        help_text=_("FQDN of the domain controller to use."),
        blank=True,
        null=True
    )
    ad_gcname = models.CharField(
        verbose_name=_("Global Catalog Server"),
        max_length=120,
        help_text=_("FQDN of the global catalog server to use."),
        blank=True,
        null=True
    )
    ad_kerberos_realm = models.ForeignKey(
        KerberosRealm,
        verbose_name=_("Kerberos Realm"),
        on_delete=models.SET_NULL,
        blank=True,
        null=True
    )
    ad_kerberos_principal = models.ForeignKey(
        KerberosPrincipal,
        verbose_name=_("Kerberos Principal"),
        on_delete=models.SET_NULL,
        blank=True,
        null=True
    )
    ad_timeout = models.IntegerField(
        verbose_name=_("AD timeout"),
        help_text=_("Timeout for AD related commands."),
        default=60
    )
    ad_dns_timeout = models.IntegerField(
        verbose_name=_("DNS timeout"),
        help_text=_("Timeout for AD DNS queries."),
        default=60
    )
    ad_idmap_backend = models.CharField(
        verbose_name=_("Idmap backend"),
        choices=choices.IDMAP_CHOICES(),
        max_length=120,
        help_text=_("Idmap backend for winbind."),
        default=enum_to_idmap(IDMAP_TYPE_RID)
    )
    ad_nss_info = models.CharField(
        max_length=120,
        blank=True,
        null=True,
        choices=choices.NSS_INFO_CHOICES,
        verbose_name=_("Winbind NSS Info"),
        help_text=_("This parameter is designed to control how Winbind "
                    "retrieves Name Service Information to construct a user's "
                    "home directory and login")
    )
    ad_ldap_sasl_wrapping = models.CharField(
        verbose_name=_("SASL wrapping"),
        choices=choices.LDAP_SASL_WRAPPING_CHOICES,
        max_length=120,
        help_text=_("The client ldap sasl wrapping defines whether ldap "
                    "traffic will be signed or signed and encrypted (sealed)."
                    "This option is needed in the case of Domain Controllers "
                    "enforcing the usage of signed LDAP connections (e.g. "
                    "Windows 2000 SP3 or higher). LDAP sign and seal can be "
                    "controlled with the registry key \"HKLM\System\\"
                    "CurrentControlSet\\Services\\NTDS\\Parameters\\"
                    "LDAPServerIntegrity\" on the Windows server side."
                    ),
        default='plain'
    )
    ad_enable = models.BooleanField(
        verbose_name=_("Enable"),
        default=False
    )

    def __init__(self, *args, **kwargs):
        super(ActiveDirectory, self).__init__(*args, **kwargs)

        if self.ad_bindpw:
            try:
                self.ad_bindpw = notifier().pwenc_decrypt(self.ad_bindpw)
            except Exception:
                log.debug('Failed to decrypt AD bind password', exc_info=True)
                self.ad_bindpw = ''
        self._ad_bindpw_encrypted = False

        self.ds_type = DS_TYPE_ACTIVEDIRECTORY
        self.ds_name = enum_to_directoryservice(self.ds_type)

    def save(self, **kwargs):
        if self.ad_bindpw and not self._ad_bindpw_encrypted:
            self.ad_bindpw = notifier().pwenc_encrypt(
                self.ad_bindpw
            )
            self._ad_bindpw_encrypted = True
        super(ActiveDirectory, self).save(**kwargs)

        if not self.ad_kerberos_realm:
            from freenasUI.common.freenasldap import (
                FreeNAS_ActiveDirectory,
                FLAGS_DBINIT
            )

            try:
                FreeNAS_ActiveDirectory(flags=FLAGS_DBINIT)

                kr = KerberosRealm.objects.filter(
                    krb_realm=self.ad_domainname.upper()
                )
                if kr:
                    kr = kr[0]
                else:
                    kr = KerberosRealm()
                    kr.krb_realm = self.ad_domainname.upper()
                    kr.save()

                self.ad_kerberos_realm = kr
                super(ActiveDirectory, self).save()

            except Exception as e:
                log.debug(
                    "ActiveDirectory: Unable to create kerberos realm: %s",
                    e, exc_info=True
                )

    class Meta:
        verbose_name = _("Active Directory")
        verbose_name_plural = _("Active Directory")
Example #5
0
class LDAP(DirectoryServiceBase):
    ldap_hostname = models.CharField(
        verbose_name=_("Hostname"),
        max_length=120,
        help_text=_("The name or IP address of the LDAP server"),
        blank=True)
    ldap_basedn = models.CharField(
        verbose_name=_("Base DN"),
        max_length=120,
        help_text=_("The default base Distinguished Name (DN) to use for "
                    "searches, eg dc=test,dc=org"),
        blank=True)
    ldap_binddn = models.CharField(
        verbose_name=_("Bind DN"),
        max_length=256,
        help_text=_("The distinguished name with which to bind to the "
                    "directory server, e.g. cn=admin,dc=test,dc=org"),
        blank=True)
    ldap_bindpw = models.CharField(
        verbose_name=_("Bind password"),
        max_length=120,
        help_text=_("The credentials with which to bind."),
        blank=True)
    ldap_anonbind = models.BooleanField(
        verbose_name=_("Allow Anonymous Binding"), default=False)
    ldap_kerberos_realm = models.ForeignKey(KerberosRealm,
                                            verbose_name=_("Kerberos Realm"),
                                            on_delete=models.SET_NULL,
                                            blank=True,
                                            null=True)
    ldap_kerberos_principal = models.CharField(
        verbose_name=_("Kerberos Princpal"), max_length=255, blank=True)
    ldap_ssl = models.CharField(
        verbose_name=_("Encryption Mode"),
        max_length=120,
        help_text=_("This parameter specifies whether to use SSL/TLS, e.g."
                    " on/off/start_tls"),
        choices=choices.LDAP_SSL_CHOICES,
        default='off')
    ldap_certificate = models.ForeignKey(Certificate,
                                         verbose_name=_("Certificate"),
                                         on_delete=models.SET_NULL,
                                         blank=True,
                                         null=True,
                                         limit_choices_to={
                                             'cert_certificate__isnull': False,
                                             'cert_privatekey__isnull': False
                                         })
    ldap_validate_certificates = models.BooleanField(
        verbose_name=_("Perform strict certificate validation"),
        default=True,
        help_text=
        _("Request certificate from remote LDAP server. If no certificate is provided "
          "or a bad certificate is provided, immediately terminate LDAP session. "
          "This parameter corresponds with the ldap.conf parameter TLS_REQCERT demand. "
          "TLS_REQCERT allow is set if unchecked. "))
    ldap_disable_freenas_cache = models.BooleanField(
        verbose_name=_("Disable LDAP user/group cache"),
        help_text=
        _("Set to disable caching LDAP users and groups in large LDAP environments. "
          "When caching is disabled, LDAP users and groups do not appear in dropdown "
          "menus, but are still accepted when manually entered."),
        default=False)
    ldap_timeout = models.IntegerField(
        verbose_name=_("LDAP timeout"),
        help_text=_("Timeout for LDAP related commands."),
        default=10)
    ldap_dns_timeout = models.IntegerField(
        verbose_name=_("DNS timeout"),
        help_text=_("Timeout for LDAP DNS queries."),
        default=10)
    ldap_idmap_backend = models.CharField(
        verbose_name=_("Idmap Backend"),
        choices=choices.IDMAP_CHOICES(),
        max_length=120,
        help_text=_("Idmap backend for winbind."),
        default=enum_to_idmap(IDMAP_TYPE_LDAP))
    ldap_has_samba_schema = models.BooleanField(verbose_name=_("Samba Schema"),
                                                default=False)
    ldap_auxiliary_parameters = models.TextField(
        verbose_name=_("Auxiliary Parameters"),
        blank=True,
        help_text=_("These parameters are added to nslcd.conf"))
    ldap_schema = models.CharField(verbose_name=("Schema"),
                                   choices=choices.LDAP_SCHEMA_CHOICES,
                                   max_length=120,
                                   help_text=_("LDAP Schema type."),
                                   default=choices.LDAP_SCHEMA_CHOICES[0][0])
    ldap_enable = models.BooleanField(verbose_name=_("Enable"), default=False)

    def __init__(self, *args, **kwargs):
        super(LDAP, self).__init__(*args, **kwargs)

        if self.ldap_bindpw:
            try:
                self.ldap_bindpw = notifier().pwenc_decrypt(self.ldap_bindpw)
            except Exception:
                log.debug('Failed to decrypt LDAP bind password',
                          exc_info=True)
                self.ldap_bindpw = ''
        self._ldap_bindpw_encrypted = False

        self.ds_type = DS_TYPE_LDAP
        self.ds_name = enum_to_directoryservice(self.ds_type)

    def save(self, *args, **kwargs):
        if self.ldap_bindpw and not self._ldap_bindpw_encrypted:
            self.ldap_bindpw = notifier().pwenc_encrypt(self.ldap_bindpw)
            self._ldap_bindpw_encrypted = True
        super(LDAP, self).save(*args, **kwargs)

    class Meta:
        verbose_name = _("LDAP")
        verbose_name_plural = _("LDAP")