Ejemplo n.º 1
0
    def _getEmailSubject(self, user=""):
        """
        Could be used to implement some more complex logic similar to the
        SMS token where the SMS text is read from a policy.

        :return: The message that is sent to the user. It should contain
            at least the placeholder <otp>
        :rtype: string
        """
        subject = ''

        if not user:
            return subject

        realm = user.realm
        login = user.login

        policies = get_client_policy(context['Client'], scope="authentication",
                                     realm=realm, user=login,
                                     action="emailsubject")

        if policies:
            subject = getPolicyActionValue(policies, "emailsubject",
                                           is_string=True)

        return subject
Ejemplo n.º 2
0
def _lookup_provider_policies(provider_type):
    """
    helper, to prevent deleting a provider while it is still used in a policy

    :param provider_type: the type of provider: sms or email
    :return: a dictionary with provider names as key and list of policy names
    """
    provider_policies = {}

    # lookup the policy action name
    provider_action_name = Policy_action_name.get(provider_type)
    if not provider_action_name:
        raise Exception('unknown provider_type for policy lookup! %r'
                        % provider_type)

    # now have a look at all authentication policies
    policies = getPolicy({'scope': 'authentication',
                          "action": provider_action_name,
                          })

    for policy in policies:
        provider_name = getPolicyActionValue(policies,
                                             provider_action_name,
                                             is_string=True)
        if provider_name not in provider_policies:
            provider_policies[provider_name] = []

        provider_policies[provider_name].append(policy)

    return provider_policies
Ejemplo n.º 3
0
def get_voice_language(user="", realm=""):
    """
    This function returns the voice language as defined in the policy
    authentication/voice_language. If no such policy is defined, the
    function returns the fallback message "en"

    :return: string
    """

    voice_language = "en"

    pol = get_client_policy(context['Client'],
                            scope="authentication",
                            realm=realm,
                            user=user,
                            action="voice_language")

    if len(pol) > 0:
        voice_language = getPolicyActionValue(pol,
                                              "voice_language",
                                              is_string=True)

        log.debug("[get_voice_language] got the voice_language = %s",
                  voice_language)

    return voice_language
Ejemplo n.º 4
0
    def _is_valid_facet(self, origin):
        """
        check if origin is in the valid facets if the u2f_valid_facets policy is set.
        Otherwise check if the origin matches the previously saved origin

        :return:          boolean - True if supported, False if unsupported
        """
        is_valid = False

        # Get the valid facets as specified in the enrollment policy 'u2f_valid_facets'
        # for the specific realm
        valid_facets_action_value = ""
        realms = self.token.getRealmNames()
        if len(realms) > 0:
            get_policy_params = {"action": "u2f_valid_facets", "scope": "enrollment", "realm": realms[0]}
            policies = getPolicy(get_policy_params, context=self.context)
            valid_facets_action_value = getPolicyActionValue(policies, "u2f_valid_facets", String=True)

        if valid_facets_action_value != "":
            # 'u2f_valid_facets' policy is set - check if origin is in valid facets list
            valid_facets = valid_facets_action_value.split(";")
            for facet in valid_facets:
                facet = facet.strip()
            if origin in valid_facets:
                is_valid = True
        else:
            # 'u2f_valid_facets' policy is empty or not set
            # check if origin matches the origin stored in the token info or save it if no origin
            # is stored yet
            appId = self._get_app_id()
            if appId == origin:
                is_valid = True

        return is_valid
Ejemplo n.º 5
0
def _lookup_provider_policies(provider_type):
    """
    helper, to prevent deleting a provider while it is still used in a policy

    :param provider_type: the type of provider: sms or email
    :return: a dictionary with provider names as key and list of policy names
    """
    provider_policies = {}

    # lookup the policy action name
    provider_action_name = Policy_action_name.get(provider_type)
    if not provider_action_name:
        raise Exception('unknown provider_type for policy lookup! %r' %
                        provider_type)

    # now have a look at all authentication policies
    policies = getPolicy({
        'scope': 'authentication',
        "action": provider_action_name,
    })

    for policy in policies:
        provider_name = getPolicyActionValue(policies,
                                             provider_action_name,
                                             is_string=True)
        if provider_name not in provider_policies:
            provider_policies[provider_name] = []

        provider_policies[provider_name].append(policy)

    return provider_policies
Ejemplo n.º 6
0
def get_auth_smstext(user="", realm="", context=None):
    '''
    this function checks the policy scope=authentication, action=smstext
    This is a string policy
    The function returns the tuple (bool, string),
        bool: If a policy is defined
        string: the string to use
    '''
    # the default string is the OTP value
    ret = False
    smstext = "<otp>"

    pol = getPolicy(
        {
            'scope': 'authentication',
            'realm': realm,
            "action": "smstext"
        },
        context=context)

    if len(pol) > 0:
        smstext = getPolicyActionValue(pol, "smstext", String=True)
        log.debug("[get_auth_smstext] got the smstext = %s" % smstext)
        ret = True

    return ret, smstext
Ejemplo n.º 7
0
    def get_mobile_number(self, user=None):
        '''
        get the mobile number
            - from the token info or
            - if the policy allowes it, from the user info
        '''

        if not user:
            return self._getPhone()

        pol = get_client_policy(context['Client'],
                                scope="authentication",
                                user=user,
                                action="sms_dynamic_mobile_number")

        if not pol:
            return self._getPhone()

        get_dynamic = getPolicyActionValue(pol,
                                           "sms_dynamic_mobile_number",
                                           is_string=True)

        if not get_dynamic:
            return self._getPhone()

        user_detail = getUserDetail(user)
        return user_detail.get('mobile', self._getPhone())
Ejemplo n.º 8
0
    def _getEmailSubject(self, user=""):
        """
        Could be used to implement some more complex logic similar to the
        SMS token where the SMS text is read from a policy.

        :return: The message that is sent to the user. It should contain
            at least the placeholder <otp>
        :rtype: string
        """
        subject = ''

        if not user:
            return subject

        realm = user.realm
        login = user.login

        policies = getPolicy({'scope': 'authentication',
                              'realm': realm,
                              "action": "emailsubject",
                              "user": login},
                             context=self.context
                             )
        if policies:
            subject = getPolicyActionValue(policies, "emailsubject",
                                           is_string=True)

        return subject
Ejemplo n.º 9
0
    def valid_facets(self, realm=None):
        """
        Show the JSON output for the valid facets configured by the enrollment
        policy 'u2f_valid_facets'. The form of the JSON output is specified by
        the FIDO Alliance.
        """
        if realm is None:
            realm = getDefaultRealm()

        # Get the valid facets as specified in the enrollment policy 'u2f_valid_facets'
        # for the specific realm
        get_policy_params = {
            'action': 'u2f_valid_facets',
            'scope': 'enrollment',
            'realm': realm
            }
        valid_facets_action_value = getPolicyActionValue(getPolicy(get_policy_params),
                                                         'u2f_valid_facets',
                                                         String=True
                                                         )
        # the action value contains the semicolon-separated list of valid facets
        valid_facets = valid_facets_action_value.split(';')

        # Prepare the response
        response.content_type = 'application/fido.trusted-­apps+json'  # as specified by FIDO
        response_dict = {
            "trustedFacets": [{
                "version": {"major": 1, "minor": 0},
                "ids": []
                }]
            }
        for facet in valid_facets:
            facet = facet.strip()
            response_dict['trustedFacets'][0]['ids'].append(facet)
        return json.dumps(response_dict)
Ejemplo n.º 10
0
    def _get_email_address(self, user=None):
        '''
        get the email address
            - from the token info or
            - if the policy allowes it, from the user info
        '''

        if not user:
            return self._email_address

        pol = get_client_policy(
            context['Client'], scope="authentication", user=user,
            action="dynamic_email_address")

        if not pol:
            return self._email_address

        get_dynamic = getPolicyActionValue(
            pol, "dynamic_email_address", is_string=True)

        if not get_dynamic:
            return self._email_address

        user_detail = getUserDetail(user)
        return user_detail.get('email', self._email_address)
Ejemplo n.º 11
0
    def valid_facets(self, realm=None):
        """
        Show the JSON output for the valid facets configured by the enrollment
        policy 'u2f_valid_facets'. The form of the JSON output is specified by
        the FIDO Alliance.
        """
        if realm is None:
            realm = getDefaultRealm()

        # Get the valid facets as specified in the enrollment policy 'u2f_valid_facets'
        # for the specific realm
        get_policy_params = {
            'action': 'u2f_valid_facets',
            'scope': 'enrollment',
            'realm': realm
            }
        valid_facets_action_value = getPolicyActionValue(
                                        getPolicy(get_policy_params),
                                        'u2f_valid_facets',
                                        is_string=True)
        # the action value contains the semicolon-separated list of valid facets
        valid_facets = valid_facets_action_value.split(';')

        # Prepare the response
        response.content_type = 'application/fido.trusted-­apps+json'  # as specified by FIDO
        response_dict = {
            "trustedFacets": [{
                "version": {"major": 1, "minor": 0},
                "ids": []
                }]
            }
        for facet in valid_facets:
            facet = facet.strip()
            response_dict['trustedFacets'][0]['ids'].append(facet)
        return json.dumps(response_dict)
Ejemplo n.º 12
0
def get_provider_from_policy(provider_type,
                             realm=None,
                             user=None,
                             scope='authentication',
                             action=None):
    """
    interface for the provider user like email token or sms token

    :param provider_type: 'push', 'email' or 'sms
    :param user: the user, who should receive the message, used for
                 the policy lookup
    :return: the list of all identified providers by name
    """

    # check if the provider is defined in a policy
    provider_name = None

    # lookup the policy action name
    provider_action_name = Policy_action_name.get(provider_type)
    if not provider_action_name:
        raise Exception('unknown provider_type for policy lookup! %r' %
                        provider_type)

    if user is None:
        raise Exception('unknown user for policy lookup! %r' % user)

    if user and user.login:
        realm = user.realm

    if not action:
        action = provider_action_name

    policies = get_client_policy(request_context['Client'],
                                 scope=scope,
                                 action=action,
                                 realm=realm,
                                 user=user.login)

    if not policies:

        default_provider = _get_default_provider_name(provider_type)

        if default_provider:
            return [default_provider]

        return []

    provider_names = getPolicyActionValue(policies, action, is_string=True)

    providers = []

    for entry in [x.strip() for x in provider_names.split(' ')]:
        if entry:
            providers.append(entry)

    return providers
Ejemplo n.º 13
0
def get_provider_from_policy(provider_type, realm=None, user=None):
    """
    interface for the provider user like email token or sms token

    :param provider_type: 'push', 'email' or 'sms
    :param user: the user, who should receive the message, used for
                 the policy lookup
    :return: the list of all identified providers by name
    """

    # check if the provider is defined in a policy
    provider_name = None

    # lookup the policy action name
    provider_action_name = Policy_action_name.get(provider_type)
    if not provider_action_name:
        raise Exception('unknown provider_type for policy lookup! %r'
                        % provider_type)

    if user is None:
        raise Exception('unknown user for policy lookup! %r'
                        % user)

    if user and user.login:
        realm = user.realm

    policies = get_client_policy(request_context['Client'],
                                 scope='authentication',
                                 action=provider_action_name, realm=realm,
                                 user=user.login)

    if not policies:

        default_provider = _get_default_provider_name(provider_type)

        if default_provider:
            return [default_provider]

        return []

    provider_names = getPolicyActionValue(policies,
                                         provider_action_name,
                                         is_string=True)

    providers = []

    for entry in [x.strip() for x in provider_names.split(' ')]:
        if entry:
            providers.append(entry)

    return providers
Ejemplo n.º 14
0
def get_single_auth_policy(policy_name, user=None, realms=None):
    """
    Retrieves a policy value and checks if the value is consistent
    across realms.

    :param policy_name: the name of the policy, e.g:
        * qrtoken_pairing_callback_url
        * qrtoken_pairing_callback_sms
        * qrtoken_challenge_response_url
        * qrtoken_challenge_response_sms

    :param realms: the realms that his policy should be effective in
    """

    action_values = []
    login = None
    ret = None

    if user and user.login and user.realm:
        realms = [user.realm]
        login = user.login

    if realms is None or len(realms) == 0:
        realms = ['/:no realm:/']

    params = {"scope": "authentication",
              'action': policy_name}

    for realm in realms:
        params['realm'] = realm
        if login:
            params['user'] = login

        policy = getPolicy(params)
        action_value = getPolicyActionValue(policy, policy_name,
                                            is_string=True)
        if action_value:
            action_values.append(action_value)

    if len(action_values) > 1:
        for value in action_values:
            if value != action_values[0]:
                raise Exception('conflicting policy values %r found for '
                                'realm set: %r' % (action_values, realms))
    if action_values:
        ret = action_values[0]

    return ret
Ejemplo n.º 15
0
def get_single_auth_policy(policy_name, user=None, realms=None):
    """
    Retrieves a policy value and checks if the value is consistent
    across realms.

    :param policy_name: the name of the policy, e.g:
        * qrtoken_pairing_callback_url
        * qrtoken_pairing_callback_sms
        * qrtoken_challenge_response_url
        * qrtoken_challenge_response_sms

    :param realms: the realms that his policy should be effective in
    """

    action_values = []
    login = None
    ret = None

    if user and user.login and user.realm:
        realms = [user.realm]
        login = user.login

    if realms is None or len(realms) == 0:
        realms = ['/:no realm:/']

    params = {"scope": "authentication", 'action': policy_name}

    for realm in realms:
        params['realm'] = realm
        if login:
            params['user'] = login

        policy = getPolicy(params)
        action_value = getPolicyActionValue(policy,
                                            policy_name,
                                            is_string=True)
        if action_value:
            action_values.append(action_value)

    if len(action_values) > 1:
        for value in action_values:
            if value != action_values[0]:
                raise Exception('conflicting policy values %r found for '
                                'realm set: %r' % (action_values, realms))
    if action_values:
        ret = action_values[0]

    return ret
Ejemplo n.º 16
0
def is_phone_editable(user=""):
    """
    this function checks the policy scope=selfservice, action=edit_sms
    This is a int policy, while the '0' is a deny
    """
    # the default string is the OTP value
    ret = True
    realm = user.realm
    login = user.login

    policies = getPolicy({"scope": "selfservice", "realm": realm, "action": "edit_sms", "user": login})
    if policies:
        edit_sms = getPolicyActionValue(policies, "edit_sms")
        if edit_sms == 0:
            ret = False

    return ret
Ejemplo n.º 17
0
def notify_user(user, action, info, required=False):
    """
    notify user via email, sms or other method (http/whatsapp...)

    :param user: the user who should be notified
    :param action: action is currently the notification action like
                   enrollment, setPin, which are defined in the
                   notification policies
    :param info: generic dict which is action specific
    :param required: if True an exception is raised if no notification could
                     be send eg if no provider is defined or could be found

    :return: boolean - true if notification is enabled
    """

    policies = get_client_policy(request_context['Client'],
                                 scope='notification',
                                 action=action,
                                 realm=user.realm,
                                 user=user.login)

    provider_specs = getPolicyActionValue(policies, action, is_string=True)
    if not isinstance(provider_specs, list):
        provider_specs = [provider_specs]

    # TODO: use the ResouceSchduler to handle failover

    for provider_spec in provider_specs:

        provider_type, _sep, provider_name = provider_spec.partition('::')

        if provider_type == 'email':
            notify_user_by_email(provider_name, user, action, info)
            return True

        # elif provider_type == 'sms':
        #    notify_user_by_email(provider_name, user, action, info)

    log.info('Failed to notify user %r', user)

    if required:
        raise NotificationException(
            'No notification has been sent - %r provider defined?' % action)

    return False
Ejemplo n.º 18
0
    def _is_valid_facet(self, origin):
        """
        check if origin is in the valid facets if the u2f_valid_facets policy is set.
        Otherwise check if the origin matches the previously saved origin

        :return:          boolean - True if supported, False if unsupported
        """
        is_valid = False

        # Get the valid facets as specified in the enrollment policy 'u2f_valid_facets'
        # for the specific realm
        valid_facets_action_value = ''
        realms = self.token.getRealmNames()
        if len(realms) > 0:
            get_policy_params = {
                'action': 'u2f_valid_facets',
                'scope': 'enrollment',
                'realm': realms[0]
                }
            valid_facets_action_value = getPolicyActionValue(getPolicy(get_policy_params),
                                                             'u2f_valid_facets',
                                                             String=True
                                                             )

        if valid_facets_action_value != '':
            # 'u2f_valid_facets' policy is set - check if origin is in valid facets list
            valid_facets = valid_facets_action_value.split(';')
            for facet in valid_facets:
                facet = facet.strip()
            if origin in valid_facets:
                is_valid = True
        else:
            # 'u2f_valid_facets' policy is empty or not set
            # check if origin matches the origin stored in the token info or save it if no origin
            # is stored yet
            appId = self.getFromTokenInfo('appId', None)
            if appId is None:
                self.addToTokenInfo('appId', origin)
                is_valid = True
            else:
                if origin == appId:
                    is_valid = True

        return is_valid
Ejemplo n.º 19
0
    def _is_valid_facet(self, origin):
        """
        check if origin is in the valid facets if the u2f_valid_facets policy is set.
        Otherwise check if the origin matches the previously saved origin

        :return:          boolean - True if supported, False if unsupported
        """
        is_valid = False

        # Get the valid facets as specified in the enrollment policy 'u2f_valid_facets'
        # for the specific realm
        valid_facets_action_value = ''
        realms = self.token.getRealmNames()
        if len(realms) > 0:
            get_policy_params = {
                'action': 'u2f_valid_facets',
                'scope': 'enrollment',
                'realm': realms[0]
            }
            valid_facets_action_value = getPolicyActionValue(
                getPolicy(get_policy_params), 'u2f_valid_facets', String=True)

        if valid_facets_action_value != '':
            # 'u2f_valid_facets' policy is set - check if origin is in valid facets list
            valid_facets = valid_facets_action_value.split(';')
            for facet in valid_facets:
                facet = facet.strip()
            if origin in valid_facets:
                is_valid = True
        else:
            # 'u2f_valid_facets' policy is empty or not set
            # check if origin matches the origin stored in the token info or save it if no origin
            # is stored yet
            appId = self.getFromTokenInfo('appId', None)
            if appId is None:
                self.addToTokenInfo('appId', origin)
                is_valid = True
            else:
                if origin == appId:
                    is_valid = True

        return is_valid
Ejemplo n.º 20
0
def get_auth_smstext(user="", realm=""):
    """
    this function checks the policy scope=authentication, action=smstext
    This is a string policy
    The function returns the tuple (bool, string),
        bool: If a policy is defined
        string: the string to use
    """
    # the default string is the OTP value
    ret = False
    smstext = "<otp>"

    pol = getPolicy({"scope": "authentication", "realm": realm, "action": "smstext"})

    if len(pol) > 0:
        smstext = getPolicyActionValue(pol, "smstext", String=True)
        log.debug("[get_auth_smstext] got the smstext = %s" % smstext)
        ret = True

    return ret, smstext
Ejemplo n.º 21
0
def is_email_editable(user=""):
    '''
    this function checks the policy scope=selfservice, action=edit_email
    This is a int policy, while the '0' is a deny
    '''
    ret = True
    realm = user.realm
    login = user.login

    policies = getPolicy({'scope': 'selfservice',
                          'realm': realm,
                          "action": "edit_email",
                          "user": login},
                          )
    if policies:
        edit_email = getPolicyActionValue(policies, "edit_email")
        if edit_email == 0:
            ret = False

    return ret
Ejemplo n.º 22
0
def is_email_editable(user=""):
    '''
    this function checks the policy scope=selfservice, action=edit_email
    This is a int policy, while the '0' is a deny
    '''
    ret = True
    realm = user.realm
    login = user.login

    policies = getPolicy({'scope': 'selfservice',
                          'realm': realm,
                          "action": "edit_email",
                          "user": login},)

    if policies:
        edit_email = getPolicyActionValue(policies, "edit_email")
        if edit_email == 0:
            ret = False

    return ret
Ejemplo n.º 23
0
def is_phone_editable(user=""):
    '''
    this function checks the policy scope=selfservice, action=edit_sms
    This is a int policy, while the '0' is a deny
    '''
    # the default string is the OTP value
    ret = True
    realm = user.realm
    login = user.login

    policies = getPolicy({'scope': 'selfservice',
                          'realm': realm,
                          "action": "edit_sms",
                          "user": login})
    if policies:
        edit_sms = getPolicyActionValue(policies, "edit_sms")
        if edit_sms == 0:
            ret = False

    return ret
Ejemplo n.º 24
0
def get_auth_smstext(user="", realm=""):
    '''
    this function checks the policy scope=authentication, action=smstext
    This is a string policy
    The function returns the tuple (bool, string),
        bool: If a policy is defined
        string: the string to use
    '''
    # the default string is the OTP value
    ret = False
    smstext = "<otp>"

    pol = get_client_policy(context['Client'], scope="authentication",
                            realm=realm, user=user, action="smstext")

    if len(pol) > 0:
        smstext = getPolicyActionValue(pol, "smstext", is_string=True)
        log.debug("[get_auth_smstext] got the smstext = %s" % smstext)
        ret = True

    return ret, smstext
Ejemplo n.º 25
0
def is_phone_editable(user="", context=None):
    '''
    this function checks the policy scope=selfservice, action=edit_sms
    This is a int policy, while the '0' is a deny
    '''
    # the default string is the OTP value
    ret = True
    realm = user.realm
    login = user.login

    policies = getPolicy({'scope': 'selfservice',
                          'realm': realm,
                          "action": "edit_sms",
                          "user": login},
                          context=context)
    if policies:
        edit_sms = getPolicyActionValue(policies, "edit_sms")
        if edit_sms == 0:
            ret = False

    return ret
Ejemplo n.º 26
0
def enforce_smstext(user="", realm=""):
    '''
    this function checks the boolean policy
                            scope=authentication,
                            action=enforce_smstext

    The function returns true if the smstext should be used instead of the
    challenge data
    :return: bool
    '''
    pol = get_client_policy(context['Client'],
                            scope="authentication",
                            realm=realm,
                            user=user,
                            action="enforce_smstext")

    if len(pol) > 0:
        enforce_smstext = getPolicyActionValue(pol, "enforce_smstext")
        log.debug("got enforce_smstext = %r" % enforce_smstext)
        return enforce_smstext or False

    return False
Ejemplo n.º 27
0
def loadProviderFromPolicy(provider_type, user=None):
    """
    interface for the provider user like email token or sms token

    :param provider_type: 'email' or 'sms
    :param user: the user, who should receive the message, used for
                 the policy lookup
    :return: the instantiated provider with already loaded config
    """

    # check if the provider is defined in a policy
    provider_name = None

    # lookup the policy action name
    provider_action_name = Policy_action_name.get(provider_type)
    if not provider_action_name:
        raise Exception('unknown provider_type for policy lookup! %r'
                        % provider_type)

    if not user:
        raise Exception('unknown user for policy lookup! %r'
                        % user)

    realm = user.realm
    login = user.login

    policies = getPolicy({'scope': 'authentication',
                          'realm': realm,
                          "action": provider_action_name,
                          "user": login},
                         )

    if policies:
        provider_name = getPolicyActionValue(policies,
                                             provider_action_name,
                                             is_string=True)

    return loadProvider(provider_type, provider_name)
Ejemplo n.º 28
0
def get_auth_smstext(user="", realm="", context=None):
    '''
    this function checks the policy scope=authentication, action=smstext
    This is a string policy
    The function returns the tuple (bool, string),
        bool: If a policy is defined
        string: the string to use
    '''
    # the default string is the OTP value
    ret = False
    smstext = "<otp>"

    pol = getPolicy({'scope': 'authentication',
                     'realm': realm,
                     "action": "smstext"},
                    context=context)

    if len(pol) > 0:
        smstext = getPolicyActionValue(pol, "smstext", is_string=True)
        log.debug("[get_auth_smstext] got the smstext = %s" % smstext)
        ret = True

    return ret, smstext
Ejemplo n.º 29
0
def loadProviderFromPolicy(provider_type, realm=None, user=None):
    """
    interface for the provider user like email token or sms token

    :param provider_type: 'push', 'email' or 'sms
    :param user: the user, who should receive the message, used for
                 the policy lookup
    :return: the instantiated provider with already loaded config
    """

    # check if the provider is defined in a policy
    provider_name = None

    # lookup the policy action name
    provider_action_name = Policy_action_name.get(provider_type)
    if not provider_action_name:
        raise Exception('unknown provider_type for policy lookup! %r'
                        % provider_type)

    if user is None:
        raise Exception('unknown user for policy lookup! %r'
                        % user)

    if user and user.login:
        realm = user.realm

    policies = get_client_policy(request_context['Client'],
                                 scope='authentication',
                                 action=provider_action_name, realm=realm,
                                 user=user.login)

    if policies:
        provider_name = getPolicyActionValue(policies,
                                             provider_action_name,
                                             is_string=True)

    return loadProvider(provider_type, provider_name)
Ejemplo n.º 30
0
def loadProviderFromPolicy(provider_type, realm=None, user=None):
    """
    interface for the provider user like email token or sms token

    :param provider_type: 'push', 'email' or 'sms
    :param user: the user, who should receive the message, used for
                 the policy lookup
    :return: the instantiated provider with already loaded config
    """

    # check if the provider is defined in a policy
    provider_name = None

    # lookup the policy action name
    provider_action_name = Policy_action_name.get(provider_type)
    if not provider_action_name:
        raise Exception('unknown provider_type for policy lookup! %r' %
                        provider_type)

    if not user:
        raise Exception('unknown user for policy lookup! %r' % user)

    if user and user.login:
        realm = user.realm

    policies = get_client_policy(request_context['Client'],
                                 scope='authentication',
                                 action=provider_action_name,
                                 realm=realm,
                                 user=user.login)

    if policies:
        provider_name = getPolicyActionValue(policies,
                                             provider_action_name,
                                             is_string=True)

    return loadProvider(provider_type, provider_name)
Ejemplo n.º 31
0
    def getInitDetail(self, params, user=None):
        """
        to complete the token normalisation, the response of the initialisation
        should be built by the token specific method, the getInitDetails
        """
        response_detail = {}

        info = self.getInfo()
        response_detail.update(info)
        response_detail['serial'] = self.getSerial()

        # get requested phase
        requested_phase = getParam(params, "phase", optional=False)

        if requested_phase == "registration1":
            # We are in registration phase 1
            # We create a 32 bytes otp key (from urandom)
            # which is used as the registration challenge
            challenge = base64.urlsafe_b64encode(binascii.unhexlify(self._genOtpKey_(32)))
            self.addToTokenInfo('challenge', challenge)

            # save the appId to the TokenInfo
            # An appId passed as parameter is preferred over an appId defined in a policy
            appId = ''
            if 'appid' in params:
                appId = params.get('appid')
            else:
                # No appId passed as parameter - fall back to the policy
                # Get the appId as specified in the enrollment policy 'u2f_app_id'
                # for the specific realm
                # If the token has multiple realms, the appIds are checked for conflicts.
                # It could be discussed whether the token should use the appId of the default
                # realm, when the token is not attached to any realms
                realms = self.token.getRealmNames()
                for realm in realms:
                    get_policy_params = {
                        'action': 'u2f_app_id',
                        'scope': 'enrollment',
                        'realm': realm
                        }
                    policy_value = getPolicyActionValue(getPolicy(get_policy_params),
                                                        'u2f_app_id',
                                                        String=True
                                                        )
                    # Check for appId conflicts
                    if appId and policy_value:
                        if appId != policy_value:
                            log.error("Conflicting appId values in u2f policies.")
                            raise Exception("Conflicting appId values in u2f policies.")
                    appId = policy_value

            if not appId:
                log.error("No appId defined.")
                raise Exception("No appId defined.")
            self.addToTokenInfo('appId', appId)

            # create U2F RegisterRequest object and append it to the response as 'message'
            appId = self._get_app_id()
            register_request = {'challenge': challenge,
                                'version': 'U2F_V2',
                                'appId': appId
                                }
            response_detail['registerrequest'] = register_request

        elif requested_phase == "registration2":
            # We are in registration phase 2
            # process the data generated by the u2f compatible token device
            registerResponse = ""

            otpkey = None
            if 'otpkey' in params:
                otpkey = params.get('otpkey')

            if otpkey is not None:
                # otpkey holds the JSON RegisterResponse object as specified by the FIDO Alliance
                try:
                    registerResponse = json.loads(otpkey)
                except ValueError as ex:
                    log.error("Invalid JSON format - value error %r", (ex))
                    raise Exception('Invalid JSON format')

                try:
                    registrationData = registerResponse['registrationData']
                    clientData = registerResponse['clientData']
                except AttributeError as ex:
                    log.error(
                        "Couldn't find keyword in JSON object - attribute error %r ", (ex))
                    raise Exception("Couldn't find keyword in JSON object")

                # registrationData and clientData are urlsafe base64 encoded
                # correct padding errors (length should be multiples of 4)
                # fill up the registrationData with '=' to the correct padding
                registrationData = registrationData + \
                    ('=' * (4 - (len(registrationData) % 4)))
                clientData = clientData + ('=' * (4 - (len(clientData) % 4)))
                registrationData = base64.urlsafe_b64decode(
                    registrationData.encode('ascii'))
                clientData = base64.urlsafe_b64decode(clientData.encode('ascii'))

                # parse the raw registrationData according to the specification
                (userPublicKey, keyHandle, X509cert, signature) = \
                    self._parseRegistrationData(registrationData)

                # check the received clientData object
                if not self._checkClientData(
                    clientData, 'registration', self.getFromTokenInfo('challenge', None)):
                    raise ValueError("Received invalid clientData object. Aborting...")

                # prepare the applicationParameter and challengeParameter needed for
                # verification of the registration signature
                appId = self._get_app_id()
                applicationParameter = sha256(appId).digest()
                challengeParameter = sha256(clientData).digest()

                # verify the registration signature
                self._validateRegistrationSignature(applicationParameter,
                                                    challengeParameter,
                                                    keyHandle,
                                                    userPublicKey,
                                                    X509cert,
                                                    signature
                                                    )

                # save the key handle and the user public key in the Tokeninfo field for
                # future use
                self.addToTokenInfo('keyHandle', base64.urlsafe_b64encode(keyHandle))
                self.addToTokenInfo('publicKey', base64.urlsafe_b64encode(userPublicKey))
                self.addToTokenInfo('counter', '0')
                self.addToTokenInfo('phase', 'authentication')
                # remove the registration challenge from the token info
                self.removeFromTokenInfo('challenge')
                # Activate the token
                self.token.LinOtpIsactive = True
            else:
                log.error("No otpkey set!")
                raise ValueError("No otpkey set")
        else:
            log.error("Unsupported phase: %s", requested_phase)
            raise Exception("Unsupported phase: %s", requested_phase)

        return response_detail
Ejemplo n.º 32
0
    def getInitDetail(self, params, user=None):
        """
        to complete the token normalisation, the response of the initialisation
        should be built by the token specific method, the getInitDetails
        """
        response_detail = {}

        info = self.getInfo()
        response_detail.update(info)
        response_detail['serial'] = self.getSerial()

        # get requested phase
        requested_phase = getParam(params, "phase", optional=False)

        if requested_phase == "registration1":
            # We are in registration phase 1
            # We create a 32 bytes otp key (from urandom)
            # which is used as the registration challenge
            challenge = base64.urlsafe_b64encode(binascii.unhexlify(self._genOtpKey_(32)))
            self.addToTokenInfo('challenge', challenge)

            # save the appId to the TokenInfo
            # An appId passed as parameter is preferred over an appId defined in a policy
            appId = ''
            if 'appid' in params:
                appId = params.get('appid')
            else:
                # No appId passed as parameter - fall back to the policy
                # Get the appId as specified in the enrollment policy 'u2f_app_id'
                # for the specific realm
                # If the token has multiple realms, the appIds are checked for conflicts.
                # It could be discussed whether the token should use the appId of the default
                # realm, when the token is not attached to any realms
                realms = self.token.getRealmNames()
                for realm in realms:
                    get_policy_params = {
                        'action': 'u2f_app_id',
                        'scope': 'enrollment',
                        'realm': realm
                        }
                    policies = getPolicy(get_policy_params, context=self.context)
                    policy_value = getPolicyActionValue(policies,
                                                        'u2f_app_id',
                                                        String=True
                                                        )
                    # Check for appId conflicts
                    if appId and policy_value:
                        if appId != policy_value:
                            log.error("Conflicting appId values in u2f policies.")
                            raise Exception("Conflicting appId values in u2f policies.")
                    appId = policy_value

            if not appId:
                log.error("No appId defined.")
                raise Exception("No appId defined.")
            self.addToTokenInfo('appId', appId)

            # create U2F RegisterRequest object and append it to the response as 'message'
            appId = self._get_app_id()
            register_request = {'challenge': challenge,
                                'version': 'U2F_V2',
                                'appId': appId
                                }
            response_detail['registerrequest'] = register_request

        elif requested_phase == "registration2":
            # We are in registration phase 2
            # process the data generated by the u2f compatible token device
            registerResponse = ""

            otpkey = None
            if 'otpkey' in params:
                otpkey = params.get('otpkey')

            if otpkey is not None:
                # otpkey holds the JSON RegisterResponse object as specified by the FIDO Alliance
                try:
                    registerResponse = json.loads(otpkey)
                except ValueError as ex:
                    log.exception("Invalid JSON format - value error %r", (ex))
                    raise Exception('Invalid JSON format')

                self._handle_client_errors(registerResponse)

                try:
                    registrationData = registerResponse['registrationData']
                    clientData = registerResponse['clientData']
                except AttributeError as ex:
                    log.exception(
                        "Couldn't find keyword in JSON object - attribute error %r ", (ex))
                    raise Exception("Couldn't find keyword in JSON object")

                # registrationData and clientData are urlsafe base64 encoded
                # correct padding errors (length should be multiples of 4)
                # fill up the registrationData with '=' to the correct padding
                registrationData = registrationData + \
                    ('=' * (4 - (len(registrationData) % 4)))
                clientData = clientData + ('=' * (4 - (len(clientData) % 4)))
                registrationData = base64.urlsafe_b64decode(
                    registrationData.encode('ascii'))
                clientData = base64.urlsafe_b64decode(clientData.encode('ascii'))

                # parse the raw registrationData according to the specification
                (userPublicKey, keyHandle, X509cert, signature) = \
                    self._parseRegistrationData(registrationData)

                # check the received clientData object
                if not self._checkClientData(
                    clientData, 'registration', self.getFromTokenInfo('challenge', None)):
                    raise ValueError("Received invalid clientData object. Aborting...")

                # prepare the applicationParameter and challengeParameter needed for
                # verification of the registration signature
                appId = self._get_app_id()
                applicationParameter = sha256(appId).digest()
                challengeParameter = sha256(clientData).digest()

                # verify the registration signature
                self._validateRegistrationSignature(applicationParameter,
                                                    challengeParameter,
                                                    keyHandle,
                                                    userPublicKey,
                                                    X509cert,
                                                    signature
                                                    )

                # save the key handle and the user public key in the Tokeninfo field for
                # future use
                self.addToTokenInfo('keyHandle', base64.urlsafe_b64encode(keyHandle))
                self.addToTokenInfo('publicKey', base64.urlsafe_b64encode(userPublicKey))
                self.addToTokenInfo('counter', '0')
                self.addToTokenInfo('phase', 'authentication')
                # remove the registration challenge from the token info
                self.removeFromTokenInfo('challenge')
                # Activate the token
                self.token.LinOtpIsactive = True
            else:
                log.error("No otpkey set!")
                raise ValueError("No otpkey set")
        else:
            log.error("Unsupported phase: %s", requested_phase)
            raise Exception("Unsupported phase: %s", requested_phase)

        return response_detail