Ejemplo n.º 1
0
    def execute(self, **options):
        ldap = self.api.Backend.ldap2
        if not dns_container_exists(ldap):
            return False, []

        try:
            zones = self.api.Command.dnszone_find(all=True)['result']
        except errors.NotFound:
            self.log.info('No DNS zone to update found')
            return False, []

        for zone in zones:
            update = {}
            if not zone.get('idnsallowquery'):
                # allow query from any client by default
                update['idnsallowquery'] = u'any;'

            if not zone.get('idnsallowtransfer'):
                # do not open zone transfers by default
                update['idnsallowtransfer'] = u'none;'

            old_policy = util.get_dns_forward_zone_update_policy(
                self.api.env.realm, ('A', 'AAAA'))
            if zone.get('idnsupdatepolicy', [''])[0] == old_policy:
                update['idnsupdatepolicy'] = util.get_dns_forward_zone_update_policy(\
                        self.api.env.realm)

            if update:
                # FIXME: https://fedorahosted.org/freeipa/ticket/4722
                self.api.Command.dnszone_mod(
                    zone[u'idnsname'][0].make_absolute(), **update)

        return False, []
Ejemplo n.º 2
0
    def execute(self, **options):
        ldap = self.api.Backend.ldap2

        if not dns_container_exists(ldap):
            return False, []

        dns_principal = 'DNS/%s@%s' % (self.env.host, self.env.realm)
        dns_service_dn = DN(('krbprincipalname', dns_principal),
                            self.env.container_service,
                            self.env.basedn)

        try:
            entry = ldap.get_entry(dns_service_dn, self.limit_attributes)
        except errors.NotFound:
            # this host may not have DNS service set
            root_logger.debug("DNS: service %s not found, no need to update limits" % dns_service_dn)
            return False, []

        if all(entry.get(limit.lower(), [None])[0] == self.limit_value for limit in self.limit_attributes):
            root_logger.debug("DNS: limits for service %s already set" % dns_service_dn)
            # service is already updated
            return False, []

        limit_updates = []

        for limit in self.limit_attributes:
            limit_updates.append(dict(action='only', attr=limit,
                                      value=self.limit_value))

        dnsupdate = {'dn': dns_service_dn, 'updates': limit_updates}
        root_logger.debug("DNS: limits for service %s will be updated" % dns_service_dn)


        return False, [dnsupdate]
Ejemplo n.º 3
0
    def execute(self, **options):
        ldap = self.api.Backend.ldap2
        if not dns_container_exists(ldap):
            return False, []

        try:
            zones = self.api.Command.dnszone_find(all=True)['result']
        except errors.NotFound:
            self.log.debug('No DNS zone to update found')
            return False, []

        for zone in zones:
            update = {}
            if not zone.get('idnsallowquery'):
                # allow query from any client by default
                update['idnsallowquery'] = u'any;'

            if not zone.get('idnsallowtransfer'):
                # do not open zone transfers by default
                update['idnsallowtransfer'] = u'none;'

            old_policy = util.get_dns_forward_zone_update_policy(
                self.api.env.realm, ('A', 'AAAA'))
            if zone.get('idnsupdatepolicy', [''])[0] == old_policy:
                update['idnsupdatepolicy'] = util.get_dns_forward_zone_update_policy(\
                        self.api.env.realm)

            if update:
                # FIXME: https://fedorahosted.org/freeipa/ticket/4722
                self.api.Command.dnszone_mod(zone[u'idnsname'][0].make_absolute(),
                                        **update)

        return False, []
Ejemplo n.º 4
0
    def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
        assert isinstance(dn, DN)
        exc = None
        if dns_container_exists(ldap):
            try:
                parts = keys[-1].split('.')
                host = parts[0]
                domain = unicode('.'.join(parts[1:]))

                if options.get('ip_address'):
                    add_reverse = not options.get('no_reverse', False)

                    add_records_for_host(DNSName(host),
                                         DNSName(domain).make_absolute(),
                                         options['ip_address'],
                                         add_forward=True,
                                         add_reverse=add_reverse)
                    del options['ip_address']

                update_sshfp_record(domain, unicode(parts[0]), entry_attrs)
            except Exception as e:
                exc = e
        if options.get('random', False):
            try:
                entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword'))
            except AttributeError:
                # On the off-chance some other extension deletes this from the
                # context, don't crash.
                pass
        if exc:
            raise errors.NonFatalError(
                reason=_('The host was added but the DNS update failed with: %(exc)s') % dict(exc=exc)
            )
        set_certificate_attrs(entry_attrs)
        set_kerberos_attrs(entry_attrs, options)
        rename_ipaallowedtoperform_from_ldap(entry_attrs, options)

        if options.get('all', False):
            entry_attrs['managing'] = self.obj.get_managed_hosts(dn)
        self.obj.get_password_attributes(ldap, dn, entry_attrs)
        if entry_attrs['has_password']:
            # If an OTP is set there is no keytab, at least not one
            # fetched anywhere.
            entry_attrs['has_keytab'] = False

        convert_sshpubkey_post(ldap, dn, entry_attrs)

        return dn
Ejemplo n.º 5
0
    def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
        assert isinstance(dn, DN)
        exc = None
        if dns_container_exists(ldap):
            try:
                parts = keys[-1].split('.')
                host = parts[0]
                domain = unicode('.'.join(parts[1:]))

                if options.get('ip_address'):
                    add_reverse = not options.get('no_reverse', False)

                    add_records_for_host(DNSName(host),
                                         DNSName(domain).make_absolute(),
                                         options['ip_address'],
                                         add_forward=True,
                                         add_reverse=add_reverse)
                    del options['ip_address']

                update_sshfp_record(domain, unicode(parts[0]), entry_attrs)
            except Exception as e:
                exc = e
        if options.get('random', False):
            try:
                entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword'))
            except AttributeError:
                # On the off-chance some other extension deletes this from the
                # context, don't crash.
                pass
        if exc:
            raise errors.NonFatalError(
                reason=_('The host was added but the DNS update failed with: %(exc)s') % dict(exc=exc)
            )
        set_certificate_attrs(entry_attrs)
        set_kerberos_attrs(entry_attrs, options)
        rename_ipaallowedtoperform_from_ldap(entry_attrs, options)

        if options.get('all', False):
            entry_attrs['managing'] = self.obj.get_managed_hosts(dn)
        self.obj.get_password_attributes(ldap, dn, entry_attrs)
        if entry_attrs['has_password']:
            # If an OTP is set there is no keytab, at least not one
            # fetched anywhere.
            entry_attrs['has_keytab'] = False

        convert_sshpubkey_post(ldap, dn, entry_attrs)

        return dn
Ejemplo n.º 6
0
 def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
     assert isinstance(dn, DN)
     if options.get('ip_address') and dns_container_exists(ldap):
         parts = keys[-1].split('.')
         host = parts[0]
         domain = unicode('.'.join(parts[1:]))
         check_reverse = not options.get('no_reverse', False)
         add_records_for_host_validation('ip_address',
                 DNSName(host),
                 DNSName(domain).make_absolute(),
                 options['ip_address'],
                 check_forward=True,
                 check_reverse=check_reverse)
     if not options.get('force', False) and not 'ip_address' in options:
         util.verify_host_resolvable(keys[-1], self.log)
     if 'locality' in entry_attrs:
         entry_attrs['l'] = entry_attrs['locality']
     entry_attrs['cn'] = keys[-1]
     entry_attrs['serverhostname'] = keys[-1].split('.', 1)[0]
     if not entry_attrs.get('userpassword', False) and not options.get('random', False):
         entry_attrs['krbprincipalname'] = 'host/%s@%s' % (
             keys[-1], self.api.env.realm
         )
         if 'krbprincipalaux' not in entry_attrs['objectclass']:
             entry_attrs['objectclass'].append('krbprincipalaux')
         if 'krbprincipal' not in entry_attrs['objectclass']:
             entry_attrs['objectclass'].append('krbprincipal')
     else:
         if 'krbprincipalaux' in entry_attrs['objectclass']:
             entry_attrs['objectclass'].remove('krbprincipalaux')
         if 'krbprincipal' in entry_attrs['objectclass']:
             entry_attrs['objectclass'].remove('krbprincipal')
     if options.get('random'):
         entry_attrs['userpassword'] = ipa_generate_password(characters=host_pwd_chars)
         # save the password so it can be displayed in post_callback
         setattr(context, 'randompassword', entry_attrs['userpassword'])
     certs = options.get('usercertificate', [])
     certs_der = [x509.normalize_certificate(c) for c in certs]
     for cert in certs_der:
         x509.verify_cert_subject(ldap, keys[-1], cert)
     entry_attrs['usercertificate'] = certs_der
     entry_attrs['managedby'] = dn
     entry_attrs['objectclass'].append('ieee802device')
     entry_attrs['objectclass'].append('ipasshhost')
     update_krbticketflags(ldap, entry_attrs, attrs_list, options, False)
     if 'krbticketflags' in entry_attrs:
         entry_attrs['objectclass'].append('krbticketpolicyaux')
     return dn
Ejemplo n.º 7
0
 def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
     assert isinstance(dn, DN)
     if options.get('ip_address') and dns_container_exists(ldap):
         parts = keys[-1].split('.')
         host = parts[0]
         domain = unicode('.'.join(parts[1:]))
         check_reverse = not options.get('no_reverse', False)
         add_records_for_host_validation('ip_address',
                 DNSName(host),
                 DNSName(domain).make_absolute(),
                 options['ip_address'],
                 check_forward=True,
                 check_reverse=check_reverse)
     if not options.get('force', False) and not 'ip_address' in options:
         util.validate_host_dns(self.log, keys[-1])
     if 'locality' in entry_attrs:
         entry_attrs['l'] = entry_attrs['locality']
     entry_attrs['cn'] = keys[-1]
     entry_attrs['serverhostname'] = keys[-1].split('.', 1)[0]
     if not entry_attrs.get('userpassword', False) and not options.get('random', False):
         entry_attrs['krbprincipalname'] = 'host/%s@%s' % (
             keys[-1], self.api.env.realm
         )
         if 'krbprincipalaux' not in entry_attrs['objectclass']:
             entry_attrs['objectclass'].append('krbprincipalaux')
         if 'krbprincipal' not in entry_attrs['objectclass']:
             entry_attrs['objectclass'].append('krbprincipal')
     else:
         if 'krbprincipalaux' in entry_attrs['objectclass']:
             entry_attrs['objectclass'].remove('krbprincipalaux')
         if 'krbprincipal' in entry_attrs['objectclass']:
             entry_attrs['objectclass'].remove('krbprincipal')
     if options.get('random'):
         entry_attrs['userpassword'] = ipa_generate_password(characters=host_pwd_chars)
         # save the password so it can be displayed in post_callback
         setattr(context, 'randompassword', entry_attrs['userpassword'])
     certs = options.get('usercertificate', [])
     certs_der = map(x509.normalize_certificate, certs)
     for cert in certs_der:
         x509.verify_cert_subject(ldap, keys[-1], cert)
     entry_attrs['usercertificate'] = certs_der
     entry_attrs['managedby'] = dn
     entry_attrs['objectclass'].append('ieee802device')
     entry_attrs['objectclass'].append('ipasshhost')
     update_krbticketflags(ldap, entry_attrs, attrs_list, options, False)
     if 'krbticketflags' in entry_attrs:
         entry_attrs['objectclass'].append('krbticketpolicyaux')
     return dn
Ejemplo n.º 8
0
    def execute(self, **options):
        ldap = self.obj.backend

        if not dns_container_exists(ldap):
            return (False, False, [])

        dnsupdates = {}

        # add default and updated entries
        for dn, container, entry in ((self._write_dns_perm_dn, 'default', self._write_dns_perm_entry),
                                     (self._read_dns_perm_dn, 'default', self._read_dns_perm_entry),
                                     (self._write_dns_aci_dn, 'updates', self._write_dns_aci_entry),
                                     (self._read_dns_aci_dn, 'updates', self._read_dns_aci_entry)):

            dnsupdates[dn] = {'dn': dn, container: entry}

        return (False, True, [dnsupdates])
Ejemplo n.º 9
0
    def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
        assert isinstance(dn, DN)
        exc = None
        if dns_container_exists(ldap):
            try:
                parts = keys[-1].split('.')
                host = parts[0]
                domain = unicode('.'.join(parts[1:]))

                if options.get('ip_address'):
                    add_reverse = not options.get('no_reverse', False)

                    add_records_for_host(host, domain, options['ip_address'],
                                         add_forward=True,
                                         add_reverse=add_reverse)
                    del options['ip_address']

                update_sshfp_record(domain, unicode(parts[0]), entry_attrs)
            except Exception, e:
                exc = e
Ejemplo n.º 10
0
    def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
        assert isinstance(dn, DN)
        exc = None
        if dns_container_exists(ldap):
            try:
                parts = keys[-1].split('.')
                host = parts[0]
                domain = unicode('.'.join(parts[1:]))

                if options.get('ip_address'):
                    add_reverse = not options.get('no_reverse', False)

                    add_records_for_host(host, domain, options['ip_address'],
                                         add_forward=True,
                                         add_reverse=add_reverse)
                    del options['ip_address']

                update_sshfp_record(domain, unicode(parts[0]), entry_attrs)
            except Exception, e:
                exc = e
Ejemplo n.º 11
0
    def execute(self, **options):
        ldap = self.obj.backend

        if not dns_container_exists(ldap):
            return (False, False, [])

        dns_principal = 'DNS/%s@%s' % (self.env.host, self.env.realm)
        dns_service_dn = DN(('krbprincipalname', dns_principal),
                            self.env.container_service, self.env.basedn)

        try:
            (dn, entry) = ldap.get_entry(dns_service_dn, self.limit_attributes)
        except errors.NotFound:
            # this host may not have DNS service set
            root_logger.debug(
                "DNS: service %s not found, no need to update limits" %
                dns_service_dn)
            return (False, False, [])

        if all(
                entry.get(limit.lower(), [None])[0] == self.limit_value
                for limit in self.limit_attributes):
            root_logger.debug("DNS: limits for service %s already set" %
                              dns_service_dn)
            # service is already updated
            return (False, False, [])

        limit_updates = []

        for limit in self.limit_attributes:
            limit_updates.append('only:%s:%s' % (limit, self.limit_value))

        dnsupdates = {}
        dnsupdates[dns_service_dn] = {
            'dn': dns_service_dn,
            'updates': limit_updates
        }
        root_logger.debug("DNS: limits for service %s will be updated" %
                          dns_service_dn)

        return (False, True, [dnsupdates])
Ejemplo n.º 12
0
    def execute(self, **options):
        ldap = self.obj.backend

        if not dns_container_exists(ldap):
            return (False, False, [])

        dnsupdates = {}

        # add default and updated entries
        for dn, container, entry in ((self._write_dns_perm_dn, 'default',
                                      self._write_dns_perm_entry),
                                     (self._read_dns_perm_dn, 'default',
                                      self._read_dns_perm_entry),
                                     (self._write_dns_aci_dn, 'updates',
                                      self._write_dns_aci_entry),
                                     (self._read_dns_aci_dn, 'updates',
                                      self._read_dns_aci_entry)):

            dnsupdates[dn] = {'dn': dn, container: entry}

        return (False, True, [dnsupdates])
Ejemplo n.º 13
0
    def pre_callback(self, ldap, dn, *keys, **options):
        assert isinstance(dn, DN)
        # If we aren't given a fqdn, find it
        if _hostname_validator(None, keys[-1]) is not None:
            hostentry = api.Command['host_show'](keys[-1])['result']
            fqdn = hostentry['fqdn'][0]
        else:
            fqdn = keys[-1]
        host_is_master(ldap, fqdn)
        # Remove all service records for this host
        truncated = True
        while truncated:
            try:
                ret = api.Command['service_find'](fqdn)
                truncated = ret['truncated']
                services = ret['result']
            except errors.NotFound:
                break
            else:
                for entry_attrs in services:
                    principal = entry_attrs['krbprincipalname'][0]
                    (service, hostname, realm) = split_principal(principal)
                    if hostname.lower() == fqdn:
                        api.Command['service_del'](principal)
        updatedns = options.get('updatedns', False)
        if updatedns:
            try:
                updatedns = dns_container_exists(ldap)
            except errors.NotFound:
                updatedns = False

        if updatedns:
            # Remove DNS entries
            parts = fqdn.split('.')
            domain = unicode('.'.join(parts[1:]))
            try:
                result = api.Command['dnszone_show'](domain)['result']
                domain = result['idnsname'][0]
            except errors.NotFound:
                self.obj.handle_not_found(*keys)
            # Get all forward resources for this host
            records = api.Command['dnsrecord_find'](domain, idnsname=parts[0])['result']
            for record in records:
                if 'arecord' in record:
                    remove_fwd_ptr(record['arecord'][0], parts[0],
                                   domain, 'arecord')
                if 'aaaarecord' in record:
                    remove_fwd_ptr(record['aaaarecord'][0], parts[0],
                                   domain, 'aaaarecord')
                else:
                    # Try to delete all other record types too
                    _attribute_types = [str('%srecord' % t.lower()) for t in _record_types]
                    for attr in _attribute_types:
                        if attr not in ['arecord', 'aaaarecord'] and attr in record:
                            for i in xrange(len(record[attr])):
                                if (record[attr][i].endswith(parts[0]) or
                                    record[attr][i].endswith(fqdn+'.')):
                                    delkw = { unicode(attr) : record[attr][i] }
                                    api.Command['dnsrecord_del'](domain,
                                            record['idnsname'][0],
                                            **delkw)
                            break

        try:
            (dn, entry_attrs) = ldap.get_entry(dn, ['usercertificate'])
        except errors.NotFound:
            self.obj.handle_not_found(*keys)

        if 'usercertificate' in entry_attrs:
            cert = x509.normalize_certificate(entry_attrs.get('usercertificate')[0])
            try:
                serial = unicode(x509.get_serial_number(cert, x509.DER))
                try:
                    result = api.Command['cert_show'](unicode(serial))['result'
]
                    if 'revocation_reason' not in result:
                        try:
                            api.Command['cert_revoke'](unicode(serial), revocation_reason=4)
                        except errors.NotImplementedError:
                            # some CA's might not implement revoke
                            pass
                except errors.NotImplementedError:
                    # some CA's might not implement revoke
                    pass
            except NSPRError, nsprerr:
                if nsprerr.errno == -8183:
                    # If we can't decode the cert them proceed with
                    # removing the host.
                    self.log.info("Problem decoding certificate %s" % nsprerr.args[1])
                else:
                    raise nsprerr
Ejemplo n.º 14
0
    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
        assert isinstance(dn, DN)
        # Allow an existing OTP to be reset but don't allow a OTP to be
        # added to an enrolled host.
        if options.get('userpassword') or options.get('random'):
            entry = {}
            self.obj.get_password_attributes(ldap, dn, entry)
            if not entry['has_password'] and entry['has_keytab']:
                raise errors.ValidationError(
                    name='password',
                    error=_('Password cannot be set on enrolled host.'))

        # Once a principal name is set it cannot be changed
        if 'cn' in entry_attrs:
            raise errors.ACIError(info=_('cn is immutable'))
        if 'locality' in entry_attrs:
            entry_attrs['l'] = entry_attrs['locality']
        if 'krbprincipalname' in entry_attrs:
            entry_attrs_old = ldap.get_entry(
                dn, ['objectclass', 'krbprincipalname']
            )
            if 'krbprincipalname' in entry_attrs_old:
                msg = 'Principal name already set, it is unchangeable.'
                raise errors.ACIError(info=msg)
            obj_classes = entry_attrs_old['objectclass']
            if 'krbprincipalaux' not in obj_classes:
                obj_classes.append('krbprincipalaux')
                entry_attrs['objectclass'] = obj_classes

        # verify certificates
        certs = entry_attrs.get('usercertificate') or []
        certs_der = [x509.normalize_certificate(c) for c in certs]
        for cert in certs_der:
            x509.verify_cert_subject(ldap, keys[-1], cert)

        # revoke removed certificates
        if certs and self.api.Command.ca_is_enabled()['result']:
            try:
                entry_attrs_old = ldap.get_entry(dn, ['usercertificate'])
            except errors.NotFound:
                self.obj.handle_not_found(*keys)
            old_certs = entry_attrs_old.get('usercertificate', [])
            old_certs_der = [x509.normalize_certificate(c) for c in old_certs]
            removed_certs_der = set(old_certs_der) - set(certs_der)
            revoke_certs(removed_certs_der, self.log)

        if certs:
            entry_attrs['usercertificate'] = certs_der

        if options.get('random'):
            entry_attrs['userpassword'] = ipa_generate_password(characters=host_pwd_chars)
            setattr(context, 'randompassword', entry_attrs['userpassword'])

        if 'macaddress' in entry_attrs:
            if 'objectclass' in entry_attrs:
                obj_classes = entry_attrs['objectclass']
            else:
                _entry_attrs = ldap.get_entry(dn, ['objectclass'])
                obj_classes = _entry_attrs['objectclass']
            if 'ieee802device' not in obj_classes:
                obj_classes.append('ieee802device')
                entry_attrs['objectclass'] = obj_classes

        if options.get('updatedns', False) and dns_container_exists(ldap):
            parts = keys[-1].split('.')
            domain = unicode('.'.join(parts[1:]))
            try:
                result = api.Command['dnszone_show'](domain)['result']
                domain = result['idnsname'][0]
            except errors.NotFound:
                self.obj.handle_not_found(*keys)
            update_sshfp_record(domain, unicode(parts[0]), entry_attrs)

        if 'ipasshpubkey' in entry_attrs:
            if 'objectclass' in entry_attrs:
                obj_classes = entry_attrs['objectclass']
            else:
                _entry_attrs = ldap.get_entry(dn, ['objectclass'])
                obj_classes = entry_attrs['objectclass'] = _entry_attrs['objectclass']
            if 'ipasshhost' not in obj_classes:
                obj_classes.append('ipasshhost')

        update_krbticketflags(ldap, entry_attrs, attrs_list, options, True)

        if 'krbticketflags' in entry_attrs:
            if 'objectclass' not in entry_attrs:
                entry_attrs_old = ldap.get_entry(dn, ['objectclass'])
                entry_attrs['objectclass'] = entry_attrs_old['objectclass']
            if 'krbticketpolicyaux' not in entry_attrs['objectclass']:
                entry_attrs['objectclass'].append('krbticketpolicyaux')

        return dn
Ejemplo n.º 15
0
    def pre_callback(self, ldap, dn, *keys, **options):
        assert isinstance(dn, DN)
        # If we aren't given a fqdn, find it
        if _hostname_validator(None, keys[-1]) is not None:
            hostentry = api.Command['host_show'](keys[-1])['result']
            fqdn = hostentry['fqdn'][0]
        else:
            fqdn = keys[-1]
        host_is_master(ldap, fqdn)
        # Remove all service records for this host
        truncated = True
        while truncated:
            try:
                ret = api.Command['service_find'](fqdn)
                truncated = ret['truncated']
                services = ret['result']
            except errors.NotFound:
                break
            else:
                for entry_attrs in services:
                    principal = entry_attrs['krbprincipalname'][0]
                    (service, hostname, realm) = split_principal(principal)
                    if hostname.lower() == fqdn:
                        api.Command['service_del'](principal)
        updatedns = options.get('updatedns', False)
        if updatedns:
            try:
                updatedns = dns_container_exists(ldap)
            except errors.NotFound:
                updatedns = False

        if updatedns:
            # Remove DNS entries
            parts = fqdn.split('.')
            domain = unicode('.'.join(parts[1:]))
            try:
                result = api.Command['dnszone_show'](domain)['result']
                domain = result['idnsname'][0]
            except errors.NotFound:
                self.obj.handle_not_found(*keys)
            # Get all forward resources for this host
            records = api.Command['dnsrecord_find'](domain, idnsname=parts[0])['result']
            for record in records:
                if 'arecord' in record:
                    remove_fwd_ptr(record['arecord'][0], parts[0],
                                   domain, 'arecord')
                if 'aaaarecord' in record:
                    remove_fwd_ptr(record['aaaarecord'][0], parts[0],
                                   domain, 'aaaarecord')
                else:
                    # Try to delete all other record types too
                    _attribute_types = [str('%srecord' % t.lower())
                                        for t in _record_types]
                    for attr in _attribute_types:
                        if attr not in ['arecord', 'aaaarecord'] and attr in record:
                            for val in record[attr]:
                                if (val.endswith(parts[0]) or
                                        val.endswith(fqdn + '.')):
                                    delkw = {unicode(attr): val}
                                    api.Command['dnsrecord_del'](domain,
                                            record['idnsname'][0],
                                            **delkw)
                            break

        if self.api.Command.ca_is_enabled()['result']:
            try:
                entry_attrs = ldap.get_entry(dn, ['usercertificate'])
            except errors.NotFound:
                self.obj.handle_not_found(*keys)

            revoke_certs(entry_attrs.get('usercertificate', []), self.log)

        return dn
Ejemplo n.º 16
0
    def pre_callback(self, ldap, dn, *keys, **options):
        assert isinstance(dn, DN)
        # If we aren't given a fqdn, find it
        if _hostname_validator(None, keys[-1]) is not None:
            hostentry = api.Command['host_show'](keys[-1])['result']
            fqdn = hostentry['fqdn'][0]
        else:
            fqdn = keys[-1]
        host_is_master(ldap, fqdn)
        # Remove all service records for this host
        truncated = True
        while truncated:
            try:
                ret = api.Command['service_find'](fqdn)
                truncated = ret['truncated']
                services = ret['result']
            except errors.NotFound:
                break
            else:
                for entry_attrs in services:
                    principal = entry_attrs['krbprincipalname'][0]
                    (service, hostname, realm) = split_principal(principal)
                    if hostname.lower() == fqdn:
                        api.Command['service_del'](principal)
        updatedns = options.get('updatedns', False)
        if updatedns:
            try:
                updatedns = dns_container_exists(ldap)
            except errors.NotFound:
                updatedns = False

        if updatedns:
            # Remove A, AAAA, SSHFP and PTR records of the host
            parts = fqdn.split('.')
            domain = unicode('.'.join(parts[1:]))
            # Get all resources for this host
            rec_removed = False
            try:
                record = api.Command['dnsrecord_show'](
                    domain, parts[0])['result']
            except errors.NotFound:
                pass
            else:
                # remove PTR records first
                for attr in ('arecord', 'aaaarecord'):
                    for val in record.get(attr, []):
                        rec_removed = (
                            remove_ptr_rec(val, parts[0], domain) or
                            rec_removed
                        )
                try:
                    # remove all A, AAAA, SSHFP records of the host
                    api.Command['dnsrecord_mod'](
                        domain,
                        record['idnsname'][0],
                        arecord=[],
                        aaaarecord=[],
                        sshfprecord=[]
                        )
                except errors.EmptyModlist:
                    pass
                else:
                    rec_removed = True

            if not rec_removed:
                self.add_message(
                    messages.FailedToRemoveHostDNSRecords(
                        host=fqdn,
                        reason=_("No A, AAAA, SSHFP or PTR records found.")
                    )
                )

        if self.api.Command.ca_is_enabled()['result']:
            try:
                entry_attrs = ldap.get_entry(dn, ['usercertificate'])
            except errors.NotFound:
                self.obj.handle_not_found(*keys)

            revoke_certs(entry_attrs.get('usercertificate', []), self.log)

        return dn
Ejemplo n.º 17
0
    def pre_callback(self, ldap, dn, *keys, **options):
        assert isinstance(dn, DN)
        # If we aren't given a fqdn, find it
        if _hostname_validator(None, keys[-1]) is not None:
            hostentry = api.Command['host_show'](keys[-1])['result']
            fqdn = hostentry['fqdn'][0]
        else:
            fqdn = keys[-1]
        host_is_master(ldap, fqdn)
        # Remove all service records for this host
        truncated = True
        while truncated:
            try:
                ret = api.Command['service_find'](fqdn)
                truncated = ret['truncated']
                services = ret['result']
            except errors.NotFound:
                break
            else:
                for entry_attrs in services:
                    principal = entry_attrs['krbprincipalname'][0]
                    (service, hostname, realm) = split_principal(principal)
                    if hostname.lower() == fqdn:
                        api.Command['service_del'](principal)
        updatedns = options.get('updatedns', False)
        if updatedns:
            try:
                updatedns = dns_container_exists(ldap)
            except errors.NotFound:
                updatedns = False

        if updatedns:
            # Remove DNS entries
            parts = fqdn.split('.')
            domain = unicode('.'.join(parts[1:]))
            try:
                result = api.Command['dnszone_show'](domain)['result']
                domain = result['idnsname'][0]
            except errors.NotFound:
                self.obj.handle_not_found(*keys)
            # Get all forward resources for this host
            records = api.Command['dnsrecord_find'](domain, idnsname=parts[0])['result']
            for record in records:
                if 'arecord' in record:
                    remove_fwd_ptr(record['arecord'][0], parts[0],
                                   domain, 'arecord')
                if 'aaaarecord' in record:
                    remove_fwd_ptr(record['aaaarecord'][0], parts[0],
                                   domain, 'aaaarecord')
                else:
                    # Try to delete all other record types too
                    _attribute_types = [str('%srecord' % t.lower()) for t in _record_types]
                    for attr in _attribute_types:
                        if attr not in ['arecord', 'aaaarecord'] and attr in record:
                            for i in xrange(len(record[attr])):
                                if (record[attr][i].endswith(parts[0]) or
                                    record[attr][i].endswith(fqdn+'.')):
                                    delkw = { unicode(attr) : record[attr][i] }
                                    api.Command['dnsrecord_del'](domain,
                                            record['idnsname'][0],
                                            **delkw)
                            break

        if self.api.env.enable_ra:
            try:
                (dn, entry_attrs) = ldap.get_entry(dn, ['usercertificate'])
            except errors.NotFound:
                self.obj.handle_not_found(*keys)
            cert = entry_attrs.single_value.get('usercertificate')
            if cert:
                cert = x509.normalize_certificate(cert)
                try:
                    serial = unicode(x509.get_serial_number(cert, x509.DER))
                    try:
                        result = api.Command['cert_show'](serial)['result']
                        if 'revocation_reason' not in result:
                            try:
                                api.Command['cert_revoke'](serial,
                                                           revocation_reason=4)
                            except errors.NotImplementedError:
                                # some CA's might not implement revoke
                                pass
                    except errors.NotImplementedError:
                        # some CA's might not implement revoke
                        pass
                except NSPRError, nsprerr:
                    if nsprerr.errno == -8183:
                        # If we can't decode the cert them proceed with
                        # removing the host.
                        self.log.info("Problem decoding certificate %s" %
                                      nsprerr.args[1])
                    else:
                        raise nsprerr
Ejemplo n.º 18
0
    def execute_ad(self, *keys, **options):
        # Join domain using full credentials and with random trustdom
        # secret (will be generated by the join method)
        trustinstance = None
        if not _bindings_installed:
            raise errors.NotFound(name=_('AD Trust setup'),
                  reason=_('''Cannot perform join operation without Samba 4 support installed.
                              Make sure you have installed server-trust-ad sub-package of IPA'''))

        if 'realm_server' not in options:
            realm_server = None
        else:
            realm_server = options['realm_server']

        trustinstance = ipaserver.dcerpc.TrustDomainJoins(self.api)
        if not trustinstance.configured:
            raise errors.NotFound(name=_('AD Trust setup'),
                  reason=_('''Cannot perform join operation without own domain configured.
                              Make sure you have run ipa-adtrust-install on the IPA server first'''))

        try:
            existing_trust = api.Command['trust_show'](keys[-1])
            summary = _('Re-established trust to domain "%(value)s"')
        except errors.NotFound:
            summary = self.msg_summary
        # 1. Full access to the remote domain. Use admin credentials and
        # generate random trustdom password to do work on both sides
        if 'realm_admin' in options:
            realm_admin = options['realm_admin']
            names = realm_admin.split('@')
            if len(names) > 1:
                # realm admin name is in UPN format, user@realm, check that
                # realm is the same as the one that we are attempting to trust
                if keys[-1].lower() != names[-1].lower():
                    raise errors.ValidationError(name=_('AD Trust setup'),
                                 error=_('Trusted domain and administrator account use different realms'))
                realm_admin = names[0]

            if 'realm_passwd' not in options:
                raise errors.ValidationError(name=_('AD Trust setup'), error=_('Realm administrator password should be specified'))
            realm_passwd = options['realm_passwd']

            try:
                result = trustinstance.join_ad_full_credentials(keys[-1], realm_server, realm_admin, realm_passwd)
            except errors.NotFound, e:
                error_message=_("Unable to resolve domain controller for '%s' domain. ") % (keys[-1])
                instructions=[]
                if dns_container_exists(self.obj.backend):
                    try:
                        dns_zone = api.Command.dnszone_show(keys[-1])['result']
                        if ('idnsforwardpolicy' in dns_zone) and dns_zone['idnsforwardpolicy'][0] == u'only':
                            instructions.append(_("Forward policy is defined for it in IPA DNS, "
                                                   "perhaps forwarder points to incorrect host?"))
                    except (errors.NotFound, KeyError) as e:
                        instructions.append(_("IPA manages DNS, please verify "
                                              "your DNS configuration and "
                                              "make sure that service records "
                                              "of the '%(domain)s' domain can "
                                              "be resolved. Examples how to "
                                              "configure DNS with CLI commands "
                                              "or the Web UI can be found in "
                                              "the documentation. " ) %
                                              dict(domain=keys[-1]))
                else:
                    instructions.append(_("Since IPA does not manage DNS records, ensure DNS "
                                           "is configured to resolve '%(domain)s' domain from "
                                           "IPA hosts and back.") % dict(domain=keys[-1]))
                raise errors.NotFound(reason=error_message, instructions=instructions)

            if result is None:
                raise errors.ValidationError(name=_('AD Trust setup'),
                                             error=_('Unable to verify write permissions to the AD'))

            ret = dict(value=trustinstance.remote_domain.info['dns_domain'], verified=result['verified'])
            ret['summary'] = summary % ret
            return ret
Ejemplo n.º 19
0
    def execute_ad(self, *keys, **options):
        # Join domain using full credentials and with random trustdom
        # secret (will be generated by the join method)
        trustinstance = None
        if not _bindings_installed:
            raise errors.NotFound(
                name=_('AD Trust setup'),
                reason=
                _('''Cannot perform join operation without Samba 4 support installed.
                              Make sure you have installed server-trust-ad sub-package of IPA'''
                  ))

        if 'realm_server' not in options:
            realm_server = None
        else:
            realm_server = options['realm_server']

        trustinstance = ipaserver.dcerpc.TrustDomainJoins(self.api)
        if not trustinstance.configured:
            raise errors.NotFound(
                name=_('AD Trust setup'),
                reason=
                _('''Cannot perform join operation without own domain configured.
                              Make sure you have run ipa-adtrust-install on the IPA server first'''
                  ))

        try:
            existing_trust = api.Command['trust_show'](keys[-1])
            summary = _('Re-established trust to domain "%(value)s"')
        except errors.NotFound:
            summary = self.msg_summary
        # 1. Full access to the remote domain. Use admin credentials and
        # generate random trustdom password to do work on both sides
        if 'realm_admin' in options:
            realm_admin = options['realm_admin']
            names = realm_admin.split('@')
            if len(names) > 1:
                # realm admin name is in UPN format, user@realm, check that
                # realm is the same as the one that we are attempting to trust
                if keys[-1].lower() != names[-1].lower():
                    raise errors.ValidationError(
                        name=_('AD Trust setup'),
                        error=
                        _('Trusted domain and administrator account use different realms'
                          ))
                realm_admin = names[0]

            if 'realm_passwd' not in options:
                raise errors.ValidationError(
                    name=_('AD Trust setup'),
                    error=_(
                        'Realm administrator password should be specified'))
            realm_passwd = options['realm_passwd']

            try:
                result = trustinstance.join_ad_full_credentials(
                    keys[-1], realm_server, realm_admin, realm_passwd)
            except errors.NotFound, e:
                error_message = _(
                    "Unable to resolve domain controller for '%s' domain. "
                ) % (keys[-1])
                instructions = []
                if dns_container_exists(self.obj.backend):
                    try:
                        dns_zone = api.Command.dnszone_show(keys[-1])['result']
                        if ('idnsforwardpolicy' in dns_zone
                            ) and dns_zone['idnsforwardpolicy'][0] == u'only':
                            instructions.append(
                                _("Forward policy is defined for it in IPA DNS, "
                                  "perhaps forwarder points to incorrect host?"
                                  ))
                    except (errors.NotFound, KeyError) as e:
                        instructions.append(
                            _("IPA manages DNS, please verify "
                              "your DNS configuration and "
                              "make sure that service records "
                              "of the '%(domain)s' domain can "
                              "be resolved. Examples how to "
                              "configure DNS with CLI commands "
                              "or the Web UI can be found in "
                              "the documentation. ") % dict(domain=keys[-1]))
                else:
                    instructions.append(
                        _("Since IPA does not manage DNS records, ensure DNS "
                          "is configured to resolve '%(domain)s' domain from "
                          "IPA hosts and back.") % dict(domain=keys[-1]))
                raise errors.NotFound(reason=error_message,
                                      instructions=instructions)

            if result is None:
                raise errors.ValidationError(
                    name=_('AD Trust setup'),
                    error=_('Unable to verify write permissions to the AD'))

            ret = dict(value=trustinstance.remote_domain.info['dns_domain'],
                       verified=result['verified'])
            ret['summary'] = summary % ret
            return ret
Ejemplo n.º 20
0
    def pre_callback(self, ldap, dn, *keys, **options):
        assert isinstance(dn, DN)
        # If we aren't given a fqdn, find it
        if _hostname_validator(None, keys[-1]) is not None:
            hostentry = api.Command['host_show'](keys[-1])['result']
            fqdn = hostentry['fqdn'][0]
        else:
            fqdn = keys[-1]
        host_is_master(ldap, fqdn)
        # Remove all service records for this host
        truncated = True
        while truncated:
            try:
                ret = api.Command['service_find'](fqdn)
                truncated = ret['truncated']
                services = ret['result']
            except errors.NotFound:
                break
            else:
                for entry_attrs in services:
                    principal = entry_attrs['krbprincipalname'][0]
                    (service, hostname, realm) = split_principal(principal)
                    if hostname.lower() == fqdn:
                        api.Command['service_del'](principal)
        updatedns = options.get('updatedns', False)
        if updatedns:
            try:
                updatedns = dns_container_exists(ldap)
            except errors.NotFound:
                updatedns = False

        if updatedns:
            # Remove DNS entries
            parts = fqdn.split('.')
            domain = unicode('.'.join(parts[1:]))
            try:
                result = api.Command['dnszone_show'](domain)['result']
                domain = result['idnsname'][0]
            except errors.NotFound:
                self.obj.handle_not_found(*keys)
            # Get all forward resources for this host
            records = api.Command['dnsrecord_find'](domain, idnsname=parts[0])['result']
            for record in records:
                if 'arecord' in record:
                    remove_fwd_ptr(record['arecord'][0], parts[0],
                                   domain, 'arecord')
                if 'aaaarecord' in record:
                    remove_fwd_ptr(record['aaaarecord'][0], parts[0],
                                   domain, 'aaaarecord')
                else:
                    # Try to delete all other record types too
                    _attribute_types = [str('%srecord' % t.lower())
                                        for t in _record_types]
                    for attr in _attribute_types:
                        if attr not in ['arecord', 'aaaarecord'] and attr in record:
                            for i in xrange(len(record[attr])):
                                if (record[attr][i].endswith(parts[0]) or
                                    record[attr][i].endswith(fqdn+'.')):
                                    delkw = { unicode(attr) : record[attr][i] }
                                    api.Command['dnsrecord_del'](domain,
                                            record['idnsname'][0],
                                            **delkw)
                            break

        if self.api.Command.ca_is_enabled()['result']:
            try:
                entry_attrs = ldap.get_entry(dn, ['usercertificate'])
            except errors.NotFound:
                self.obj.handle_not_found(*keys)

            revoke_certs(entry_attrs.get('usercertificate', []), self.log)

        return dn
Ejemplo n.º 21
0
    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
        assert isinstance(dn, DN)
        # Allow an existing OTP to be reset but don't allow a OTP to be
        # added to an enrolled host.
        if options.get('userpassword') or options.get('random'):
            entry = {}
            self.obj.get_password_attributes(ldap, dn, entry)
            if not entry['has_password'] and entry['has_keytab']:
                raise errors.ValidationError(
                    name='password',
                    error=_('Password cannot be set on enrolled host.'))

        # Once a principal name is set it cannot be changed
        if 'cn' in entry_attrs:
            raise errors.ACIError(info=_('cn is immutable'))
        if 'locality' in entry_attrs:
            entry_attrs['l'] = entry_attrs['locality']
        if 'krbprincipalname' in entry_attrs:
            entry_attrs_old = ldap.get_entry(
                dn, ['objectclass', 'krbprincipalname']
            )
            if 'krbprincipalname' in entry_attrs_old:
                msg = 'Principal name already set, it is unchangeable.'
                raise errors.ACIError(info=msg)
            obj_classes = entry_attrs_old['objectclass']
            if 'krbprincipalaux' not in obj_classes:
                obj_classes.append('krbprincipalaux')
                entry_attrs['objectclass'] = obj_classes

        # verify certificates
        certs = entry_attrs.get('usercertificate') or []
        certs_der = map(x509.normalize_certificate, certs)
        for cert in certs_der:
            x509.verify_cert_subject(ldap, keys[-1], cert)

        # revoke removed certificates
        if certs and self.api.Command.ca_is_enabled()['result']:
            try:
                entry_attrs_old = ldap.get_entry(dn, ['usercertificate'])
            except errors.NotFound:
                self.obj.handle_not_found(*keys)
            old_certs = entry_attrs_old.get('usercertificate', [])
            old_certs_der = map(x509.normalize_certificate, old_certs)
            removed_certs_der = set(old_certs_der) - set(certs_der)
            revoke_certs(removed_certs_der, self.log)

        if certs:
            entry_attrs['usercertificate'] = certs_der

        if options.get('random'):
            entry_attrs['userpassword'] = ipa_generate_password(characters=host_pwd_chars)
            setattr(context, 'randompassword', entry_attrs['userpassword'])

        if 'macaddress' in entry_attrs:
            if 'objectclass' in entry_attrs:
                obj_classes = entry_attrs['objectclass']
            else:
                _entry_attrs = ldap.get_entry(dn, ['objectclass'])
                obj_classes = _entry_attrs['objectclass']
            if 'ieee802device' not in obj_classes:
                obj_classes.append('ieee802device')
                entry_attrs['objectclass'] = obj_classes

        if options.get('updatedns', False) and dns_container_exists(ldap):
            parts = keys[-1].split('.')
            domain = unicode('.'.join(parts[1:]))
            try:
                result = api.Command['dnszone_show'](domain)['result']
                domain = result['idnsname'][0]
            except errors.NotFound:
                self.obj.handle_not_found(*keys)
            update_sshfp_record(domain, unicode(parts[0]), entry_attrs)

        if 'ipasshpubkey' in entry_attrs:
            if 'objectclass' in entry_attrs:
                obj_classes = entry_attrs['objectclass']
            else:
                _entry_attrs = ldap.get_entry(dn, ['objectclass'])
                obj_classes = entry_attrs['objectclass'] = _entry_attrs['objectclass']
            if 'ipasshhost' not in obj_classes:
                obj_classes.append('ipasshhost')

        update_krbticketflags(ldap, entry_attrs, attrs_list, options, True)

        if 'krbticketflags' in entry_attrs:
            if 'objectclass' not in entry_attrs:
                entry_attrs_old = ldap.get_entry(dn, ['objectclass'])
                entry_attrs['objectclass'] = entry_attrs_old['objectclass']
            if 'krbticketpolicyaux' not in entry_attrs['objectclass']:
                entry_attrs['objectclass'].append('krbticketpolicyaux')

        return dn
Ejemplo n.º 22
0
class host_mod(LDAPUpdate):
    __doc__ = _('Modify information about a host.')

    has_output_params = LDAPUpdate.has_output_params + host_output_params
    msg_summary = _('Modified host "%(value)s"')
    member_attributes = ['managedby']

    takes_options = LDAPUpdate.takes_options + (
        Str('krbprincipalname?',
            cli_name='principalname',
            label=_('Principal name'),
            doc=_('Kerberos principal name for this host'),
            attribute=True,
        ),
        Flag('updatedns?',
            doc=_('Update DNS entries'),
            default=False,
        ),
    )

    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
        assert isinstance(dn, DN)
        # Allow an existing OTP to be reset but don't allow a OTP to be
        # added to an enrolled host.
        if options.get('userpassword') or options.get('random'):
            entry = {}
            self.obj.get_password_attributes(ldap, dn, entry)
            if not entry['has_password'] and entry['has_keytab']:
                raise errors.ValidationError(name='password', error=_('Password cannot be set on enrolled host.'))

        # Once a principal name is set it cannot be changed
        if 'cn' in entry_attrs:
            raise errors.ACIError(info=_('cn is immutable'))
        if 'locality' in entry_attrs:
            entry_attrs['l'] = entry_attrs['locality']
            del entry_attrs['locality']
        if 'krbprincipalname' in entry_attrs:
            (dn, entry_attrs_old) = ldap.get_entry(
                dn, ['objectclass', 'krbprincipalname']
            )
            if 'krbprincipalname' in entry_attrs_old:
                msg = 'Principal name already set, it is unchangeable.'
                raise errors.ACIError(info=msg)
            obj_classes = entry_attrs_old['objectclass']
            if 'krbprincipalaux' not in obj_classes:
                obj_classes.append('krbprincipalaux')
                entry_attrs['objectclass'] = obj_classes
        cert = x509.normalize_certificate(entry_attrs.get('usercertificate'))
        if cert:
            x509.verify_cert_subject(ldap, keys[-1], cert)
            (dn, entry_attrs_old) = ldap.get_entry(dn, ['usercertificate'])
            if 'usercertificate' in entry_attrs_old:
                oldcert = x509.normalize_certificate(entry_attrs_old.get('usercertificate')[0])
                try:
                    serial = unicode(x509.get_serial_number(oldcert, x509.DER))
                    try:
                        result = api.Command['cert_show'](unicode(serial))['result']
                        if 'revocation_reason' not in result:
                            try:
                                api.Command['cert_revoke'](unicode(serial), revocation_reason=4)
                            except errors.NotImplementedError:
                                # some CA's might not implement revoke
                                pass
                    except errors.NotImplementedError:
                        # some CA's might not implement revoke
                        pass
                except NSPRError, nsprerr:
                    if nsprerr.errno == -8183:
                        # If we can't decode the cert them proceed with
                        # modifying the host.
                        self.log.info("Problem decoding certificate %s" % nsprerr.args[1])
                    else:
                        raise nsprerr

            entry_attrs['usercertificate'] = cert

        if options.get('random'):
            entry_attrs['userpassword'] = ipa_generate_password(characters=host_pwd_chars)
            setattr(context, 'randompassword', entry_attrs['userpassword'])
        if 'macaddress' in entry_attrs:
            if 'objectclass' in entry_attrs:
                obj_classes = entry_attrs['objectclass']
            else:
                (_dn, _entry_attrs) = ldap.get_entry(
                    dn, ['objectclass']
                )
                obj_classes = _entry_attrs['objectclass']
            if 'ieee802device' not in obj_classes:
                obj_classes.append('ieee802device')
                entry_attrs['objectclass'] = obj_classes

        if options.get('updatedns', False) and dns_container_exists(ldap):
            parts = keys[-1].split('.')
            domain = unicode('.'.join(parts[1:]))
            try:
                result = api.Command['dnszone_show'](domain)['result']
                domain = result['idnsname'][0]
            except errors.NotFound:
                self.obj.handle_not_found(*keys)
            update_sshfp_record(domain, unicode(parts[0]), entry_attrs)

        if 'ipasshpubkey' in entry_attrs:
            if 'objectclass' in entry_attrs:
                obj_classes = entry_attrs['objectclass']
            else:
                (_dn, _entry_attrs) = ldap.get_entry(dn, ['objectclass'])
                obj_classes = entry_attrs['objectclass'] = _entry_attrs['objectclass']
            if 'ipasshhost' not in obj_classes:
                obj_classes.append('ipasshhost')

        return dn