示例#1
0
    def execute(self, *keys, **options):
        '''
        A stage entry may be taken from the Delete container.
        In that case we rather do 'MODRDN' than 'ADD'.
        '''
        if options.get('from_delete'):
            ldap = self.obj.backend

            staging_dn = self.obj.get_dn(*keys, **options)
            delete_dn = DN(staging_dn[0], self.obj.delete_container_dn,
                           api.env.basedn)

            # Check that this value is a Active user
            try:
                entry_attrs = self._exc_wrapper(keys, options,
                                                ldap.get_entry)(delete_dn,
                                                                ['dn'])
            except errors.NotFound:
                raise
            self._exc_wrapper(keys, options, ldap.move_entry_newsuperior)(
                delete_dn, str(DN(self.obj.stage_container_dn,
                                  api.env.basedn)))

            entry_attrs = entry_to_dict(entry_attrs, **options)
            entry_attrs['dn'] = delete_dn

            if self.obj.primary_key and keys[-1] is not None:
                return dict(result=entry_attrs, value=keys[-1])
            return dict(result=entry_attrs, value=u'')
        else:
            return super(stageuser_add, self).execute(*keys, **options)
示例#2
0
    def forward(self, *args, **kwargs):
        status = {'result': {self.header: 'unknown'}}

        # Get the sync URI.
        segments = list(urlparse.urlparse(self.api.env.xmlrpc_uri))
        assert segments[0] == 'https' # Ensure encryption.
        segments[2] = segments[2].replace('/xml', '/session/sync_token')
        sync_uri = urlparse.urlunparse(segments)

        # Prepare the query.
        query = {k: v for k, v in kwargs.items()
                    if k in {x.name for x in self.takes_options}}
        if args and args[0] is not None:
            obj = self.api.Object.otptoken
            query['token'] = DN((obj.primary_key.name, args[0]),
                                obj.container_dn, self.api.env.basedn)
        query = urllib.urlencode(query)

        # Sync the token.
        # pylint: disable=E1101
        handler = HTTPSHandler(ca_certs=os.path.join(self.api.env.confdir, 'ca.crt'),
                               cert_reqs=ssl.CERT_REQUIRED,
                               ssl_version=ssl.PROTOCOL_TLSv1)
        rsp = urllib2.build_opener(handler).open(sync_uri, query)
        if rsp.getcode() == 200:
            status['result'][self.header] = rsp.info().get(self.header, 'unknown')
        rsp.close()

        return status
示例#3
0
    def __dict_new_entry(self, *args, **options):
        ldap = self.obj.backend

        entry_attrs = self.args_options_2_entry(*args, **options)
        entry_attrs = ldap.make_entry(DN(), entry_attrs)

        self.process_attr_options(entry_attrs, None, args, options)

        entry_attrs['objectclass'] = deepcopy(self.obj.object_class)

        if self.obj.object_class_config:
            config = ldap.get_ipa_config()
            entry_attrs['objectclass'] = config.get(
                self.obj.object_class_config, entry_attrs['objectclass'])

        return (entry_attrs)
示例#4
0
    def normalize_manager(self, manager, container):
        """
        Given a userid verify the user's existence (in the appropriate containter) and return the dn.
        """
        if not manager:
            return None

        if not isinstance(manager, list):
            manager = [manager]
        try:
            container_dn = DN(container, api.env.basedn)
            for m in xrange(len(manager)):
                if isinstance(manager[m], DN) and manager[m].endswith(container_dn):
                    continue
                entry_attrs = self.backend.find_entry_by_attr(
                        self.primary_key.name, manager[m], self.object_class, [''],
                        container_dn
                    )
                manager[m] = entry_attrs.dn
        except errors.NotFound:
            raise errors.NotFound(reason=_('manager %(manager)s not found') % dict(manager=manager[m]))

        return manager
示例#5
0
    def forward(self, *args, **kwargs):
        status = {'result': {self.header: 'unknown'}}

        # Get the sync URI.
        segments = list(urllib.parse.urlparse(self.api.env.xmlrpc_uri))
        assert segments[0] == 'https'  # Ensure encryption.
        segments[2] = segments[2].replace('/xml', '/session/sync_token')
        # urlunparse *can* take one argument
        # pylint: disable=too-many-function-args
        sync_uri = urllib.parse.urlunparse(segments)

        # Prepare the query.
        query = {
            k: v
            for k, v in kwargs.items()
            if k in {x.name
                     for x in self.takes_options}
        }
        if args and args[0] is not None:
            obj = self.api.Object.otptoken
            query['token'] = DN((obj.primary_key.name, args[0]),
                                obj.container_dn, self.api.env.basedn)
        query = urllib.parse.urlencode(query)

        # Sync the token.
        # pylint: disable=E1101
        handler = HTTPSHandler(dbdir=paths.IPA_NSSDB_DIR,
                               tls_version_min=api.env.tls_version_min,
                               tls_version_max=api.env.tls_version_max)
        rsp = urllib.request.build_opener(handler).open(sync_uri, query)
        if rsp.getcode() == 200:
            status['result'][self.header] = rsp.info().get(
                self.header, 'unknown')
        rsp.close()

        return status
示例#6
0
        label=_('Failed logins'),
    ),
    Str('krblastsuccessfulauth',
        label=_('Last successful authentication'),
    ),
    Str('krblastfailedauth',
        label=_('Last failed authentication'),
    ),
    Str('now',
        label=_('Time now'),
    ),
   )

UPG_DEFINITION_DN = DN(('cn', 'UPG Definition'),
                       ('cn', 'Definitions'),
                       ('cn', 'Managed Entries'),
                       ('cn', 'etc'),
                       api.env.basedn)

# characters to be used for generating random user passwords
baseuser_pwdchars = string.digits + string.ascii_letters + '_,.@+-='

def validate_nsaccountlock(entry_attrs):
    if 'nsaccountlock' in entry_attrs:
        nsaccountlock = entry_attrs['nsaccountlock']
        if not isinstance(nsaccountlock, (bool, Bool)):
            if not isinstance(nsaccountlock, basestring):
                raise errors.OnlyOneValueAllowed(attr='nsaccountlock')
            if nsaccountlock.lower() not in ('true', 'false'):
                raise errors.ValidationError(name='nsaccountlock',
                    error=_('must be TRUE or FALSE'))
示例#7
0
    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
        # Fill in a default UUID when not specified.
        if entry_attrs.get('ipatokenuniqueid', None) is None:
            entry_attrs['ipatokenuniqueid'] = str(uuid.uuid4())
            dn = DN("ipatokenuniqueid=%s" % entry_attrs['ipatokenuniqueid'], dn)

        if not _check_interval(options.get('ipatokennotbefore', None),
                               options.get('ipatokennotafter', None)):
            raise ValidationError(name='not_after',
                                  error='is before the validity start')

        # Set the object class and defaults for specific token types
        options['type'] = options['type'].lower()
        entry_attrs['objectclass'] = otptoken.object_class + ['ipatoken' + options['type']]
        for ttype, tattrs in TOKEN_TYPES.items():
            if ttype != options['type']:
                for tattr in tattrs:
                    if tattr in entry_attrs:
                        del entry_attrs[tattr]

        # If owner was not specified, default to the person adding this token.
        # If managedby was not specified, attempt a sensible default.
        if 'ipatokenowner' not in entry_attrs or 'managedby' not in entry_attrs:
            result = self.api.Command.user_find(whoami=True)['result']
            if result:
                cur_uid = result[0]['uid'][0]
                prev_uid = entry_attrs.setdefault('ipatokenowner', cur_uid)
                if cur_uid == prev_uid:
                    entry_attrs.setdefault('managedby', result[0]['dn'])

        # Resolve the owner's dn
        _normalize_owner(self.api.Object.user, entry_attrs)

        # Get the issuer for the URI
        owner = entry_attrs.get('ipatokenowner', None)
        issuer = api.env.realm
        if owner is not None:
            try:
                issuer = ldap.get_entry(owner, ['krbprincipalname'])['krbprincipalname'][0]
            except (NotFound, IndexError):
                pass

        # Build the URI parameters
        args = {}
        args['issuer'] = issuer
        args['secret'] = base64.b32encode(entry_attrs['ipatokenotpkey'])
        args['digits'] = entry_attrs['ipatokenotpdigits']
        args['algorithm'] = entry_attrs['ipatokenotpalgorithm']
        if options['type'] == 'totp':
            args['period'] = entry_attrs['ipatokentotptimestep']
        elif options['type'] == 'hotp':
            args['counter'] = entry_attrs['ipatokenhotpcounter']

        # Build the URI
        label = urllib.quote(entry_attrs['ipatokenuniqueid'])
        parameters = urllib.urlencode(args)
        uri = u'otpauth://%s/%s:%s?%s' % (options['type'], issuer, label, parameters)
        setattr(context, 'uri', uri)

        attrs_list.append("objectclass")
        return dn
示例#8
0
    def execute(self, *args, **options):

        ldap = self.obj.backend

        staging_dn = self.obj.get_dn(*args, **options)
        assert isinstance(staging_dn, DN)

        # retrieve the current entry
        try:
            entry_attrs = self._exc_wrapper(args, options,
                                            ldap.get_entry)(staging_dn, ['*'])
        except errors.NotFound:
            self.obj.handle_not_found(*args)
        entry_attrs = dict((k.lower(), v) for (k, v) in entry_attrs.items())

        # Check it does not exist an active entry with the same RDN
        active_dn = DN(staging_dn[0], api.env.container_user, api.env.basedn)
        try:
            test_entry_attrs = self._exc_wrapper(args, options,
                                                 ldap.get_entry)(active_dn,
                                                                 ['dn'])
            assert isinstance(staging_dn, DN)
            raise errors.DuplicateEntry(
                message=_('active user with name "%(user)s" already exists') %
                dict(user=args[-1]))
        except errors.NotFound:
            pass

        # Check the original entry is valid
        self._check_validy(staging_dn, entry_attrs)

        # Time to build the new entry
        result_entry = {'dn': active_dn}
        new_entry_attrs = self.__dict_new_entry()
        for (attr, values) in entry_attrs.items():
            self.__merge_values(args, options, entry_attrs, new_entry_attrs,
                                attr)
            result_entry[attr] = values

        # Allow Managed entry plugin to do its work
        if 'description' in new_entry_attrs and NO_UPG_MAGIC in new_entry_attrs[
                'description']:
            new_entry_attrs['description'].remove(NO_UPG_MAGIC)
            if result_entry['description'] == NO_UPG_MAGIC:
                del result_entry['description']

        for (k, v) in new_entry_attrs.items():
            self.log.debug("new entry: k=%r and v=%r)" % (k, v))

        self._build_new_entry(ldap, staging_dn, entry_attrs, new_entry_attrs)

        # Add the Active entry
        entry = ldap.make_entry(active_dn, new_entry_attrs)
        self._exc_wrapper(args, options, ldap.add_entry)(entry)

        # Now delete the Staging entry
        try:
            self._exc_wrapper(args, options, ldap.delete_entry)(staging_dn)
        except:
            try:
                self.log.error(
                    "Fail to delete the Staging user after activating it %s " %
                    (staging_dn))
                self._exc_wrapper(args, options, ldap.delete_entry)(active_dn)
            except:
                self.log.error(
                    "Fail to cleanup activation. The user remains active %s" %
                    (active_dn))
                pass
            raise

        # add the user we just created into the default primary group
        config = ldap.get_ipa_config()
        def_primary_group = config.get('ipadefaultprimarygroup')
        group_dn = self.api.Object['group'].get_dn(def_primary_group)

        # if the user is already a member of default primary group,
        # do not raise error
        # this can happen if automember rule or default group is set
        try:
            ldap.add_entry_to_group(active_dn, group_dn)
        except errors.AlreadyGroupMember:
            pass

        # Now retrieve the activated entry
        result = self.api.Command.user_show(
            args[-1],
            all=options.get('all', False),
            raw=options.get('raw', False),
            version=options.get('version'),
        )
        result['summary'] = unicode(
            _('Stage user %s activated' % staging_dn[0].value))

        return result
示例#9
0
class stageuser(baseuser):
    """
    Stage User object
    A Stage user is not an Active user and can not be used to bind with.
    Stage container is: cn=staged users,cn=accounts,cn=provisioning,SUFFIX
    Stage entry conforms the schema
    Stage entry RDN attribute is 'uid'
    Stage entry are disabled (nsAccountLock: True) through cos
    """

    container_dn = baseuser.stage_container_dn
    label = _('Stage Users')
    label_singular = _('Stage User')
    object_name = _('stage user')
    object_name_plural = _('stage users')
    managed_permissions = {
        #
        # Stage container
        #
        # Allowed to create stage user
        'System: Add Stage User': {
            'ipapermlocation':
            DN(baseuser.stage_container_dn, api.env.basedn),
            'ipapermbindruletype':
            'permission',
            'ipapermtarget':
            DN('uid=*', baseuser.stage_container_dn, api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=*)'},
            'ipapermright': {'add'},
            'ipapermdefaultattr': {'*'},
            'default_privileges':
            {'Stage User Administrators', 'Stage User Provisioning'},
        },
        # Allow to read kerberos/password
        'System: Read Stage User password': {
            'ipapermlocation':
            DN(baseuser.stage_container_dn, api.env.basedn),
            'ipapermbindruletype':
            'permission',
            'ipapermtarget':
            DN('uid=*', baseuser.stage_container_dn, api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=*)'},
            'ipapermright': {'read', 'search', 'compare'},
            'ipapermdefaultattr': {
                'userPassword',
                'krbPrincipalKey',
            },
            'default_privileges': {'Stage User Administrators'},
        },
        # Allow to update stage user
        'System: Modify Stage User': {
            'ipapermlocation':
            DN(baseuser.stage_container_dn, api.env.basedn),
            'ipapermbindruletype':
            'permission',
            'ipapermtarget':
            DN('uid=*', baseuser.stage_container_dn, api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=*)'},
            'ipapermright': {'write'},
            'ipapermdefaultattr': {'*'},
            'default_privileges': {'Stage User Administrators'},
        },
        # Allow to delete stage user
        'System: Remove Stage User': {
            'ipapermlocation':
            DN(baseuser.stage_container_dn, api.env.basedn),
            'ipapermbindruletype':
            'permission',
            'ipapermtarget':
            DN('uid=*', baseuser.stage_container_dn, api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=*)'},
            'ipapermright': {'delete'},
            'ipapermdefaultattr': {'*'},
            'default_privileges': {'Stage User Administrators'},
        },
        # Allow to read any attributes of stage users
        'System: Read Stage Users': {
            'ipapermlocation':
            DN(baseuser.stage_container_dn, api.env.basedn),
            'ipapermbindruletype':
            'permission',
            'ipapermtarget':
            DN('uid=*', baseuser.stage_container_dn, api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=*)'},
            'ipapermright': {'read', 'search', 'compare'},
            'ipapermdefaultattr': {'*'},
            'default_privileges': {'Stage User Administrators'},
        },
        #
        # Preserve container
        #
        # Allow to read Preserved User
        'System: Read Preserved Users': {
            'ipapermlocation':
            DN(baseuser.delete_container_dn, api.env.basedn),
            'ipapermbindruletype':
            'permission',
            'ipapermtarget':
            DN('uid=*', baseuser.delete_container_dn, api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=posixaccount)'},
            'ipapermright': {'read', 'search', 'compare'},
            'ipapermdefaultattr': {'*'},
            'default_privileges': {'Stage User Administrators'},
        },
        # Allow to update Preserved User
        'System: Modify Preserved Users': {
            'ipapermlocation':
            DN(baseuser.delete_container_dn, api.env.basedn),
            'ipapermbindruletype':
            'permission',
            'ipapermtarget':
            DN('uid=*', baseuser.delete_container_dn, api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=posixaccount)'},
            'ipapermright': {'write'},
            'ipapermdefaultattr': {'*'},
            'default_privileges': {'Stage User Administrators'},
        },
        # Allow to reset Preserved User password
        'System: Reset Preserved User password': {
            'ipapermlocation':
            DN(baseuser.delete_container_dn, api.env.basedn),
            'ipapermbindruletype':
            'permission',
            'ipapermtarget':
            DN('uid=*', baseuser.delete_container_dn, api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=posixaccount)'},
            'ipapermright': {'read', 'search', 'write'},
            'ipapermdefaultattr': {
                'userPassword', 'krbPrincipalKey', 'krbPasswordExpiration',
                'krbLastPwdChange'
            },
            'default_privileges': {'Stage User Administrators'},
        },
        # Allow to delete preserved user
        'System: Remove preserved User': {
            'ipapermlocation':
            DN(baseuser.delete_container_dn, api.env.basedn),
            'ipapermbindruletype':
            'permission',
            'ipapermtarget':
            DN('uid=*', baseuser.delete_container_dn, api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=*)'},
            'ipapermright': {'delete'},
            'ipapermdefaultattr': {'*'},
            'default_privileges': {'Stage User Administrators'},
        },
        #
        # Active container
        #
        # Stage user administrators need write right on RDN when
        # the active user is deleted (preserved)
        'System: Modify User RDN': {
            'ipapermlocation':
            DN(baseuser.active_container_dn, api.env.basedn),
            'ipapermbindruletype':
            'permission',
            'ipapermtarget':
            DN('uid=*', baseuser.active_container_dn, api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=posixaccount)'},
            'ipapermright': {'write'},
            'ipapermdefaultattr': {'uid'},
            'default_privileges': {'Stage User Administrators'},
        },
        #
        # Cross containers autorization
        #
        # Allow to move active user to preserve container (user-del --preserve)
        # Note: targetfilter is the target parent container
        'System: Preserve User': {
            'ipapermlocation': DN(api.env.basedn),
            'ipapermbindruletype': 'permission',
            'ipapermtargetfrom': DN(baseuser.active_container_dn,
                                    api.env.basedn),
            'ipapermtargetto': DN(baseuser.delete_container_dn,
                                  api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=nsContainer)'},
            'ipapermright': {'moddn'},
            'default_privileges': {'Stage User Administrators'},
        },
        # Allow to move preserved user to active container (user-undel)
        # Note: targetfilter is the target parent container
        'System: Undelete User': {
            'ipapermlocation': DN(api.env.basedn),
            'ipapermbindruletype': 'permission',
            'ipapermtargetfrom': DN(baseuser.delete_container_dn,
                                    api.env.basedn),
            'ipapermtargetto': DN(baseuser.active_container_dn,
                                  api.env.basedn),
            'ipapermtargetfilter': {'(objectclass=nsContainer)'},
            'ipapermright': {'moddn'},
            'default_privileges': {'Stage User Administrators'},
        },
    }
示例#10
0
class otpconfig(LDAPObject):
    object_name = _('OTP configuration options')
    default_attributes = [
        'ipatokentotpauthwindow',
        'ipatokentotpsyncwindow',
        'ipatokenhotpauthwindow',
        'ipatokenhotpsyncwindow',
    ]

    container_dn = DN(('cn', 'otp'), ('cn', 'etc'))
    permission_filter_objectclasses = ['ipatokenotpconfig']
    managed_permissions = {
        'System: Read OTP Configuration': {
            'replaces_global_anonymous_aci': True,
            'ipapermbindruletype': 'all',
            'ipapermright': {'read', 'search', 'compare'},
            'ipapermdefaultattr': {
                'ipatokentotpauthwindow',
                'ipatokentotpsyncwindow',
                'ipatokenhotpauthwindow',
                'ipatokenhotpsyncwindow',
                'cn',
            },
        },
    }

    label = _('OTP Configuration')
    label_singular = _('OTP Configuration')

    takes_params = (
        Int(
            'ipatokentotpauthwindow',
            cli_name='totp_auth_window',
            label=_('TOTP authentication Window'),
            doc=_('TOTP authentication time variance (seconds)'),
            minvalue=5,
        ),
        Int(
            'ipatokentotpsyncwindow',
            cli_name='totp_sync_window',
            label=_('TOTP Synchronization Window'),
            doc=_('TOTP synchronization time variance (seconds)'),
            minvalue=5,
        ),
        Int(
            'ipatokenhotpauthwindow',
            cli_name='hotp_auth_window',
            label=_('HOTP Authentication Window'),
            doc=_('HOTP authentication skip-ahead'),
            minvalue=1,
        ),
        Int(
            'ipatokenhotpsyncwindow',
            cli_name='hotp_sync_window',
            label=_('HOTP Synchronization Window'),
            doc=_('HOTP synchronization skip-ahead'),
            minvalue=1,
        ),
    )

    def get_dn(self, *keys, **kwargs):
        return self.container_dn + api.env.basedn
示例#11
0
 def delete_user(self, user):
     assert isinstance(user, DN)
     return self._user_status(user,
                              DN(self.delete_container_dn, api.env.basedn))