Esempio n. 1
0
def main(client_id, user_arguments_dict, environ=None):
    """Main function used by front end"""

    if environ is None:
        environ = os.environ
    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)

    status = returnvalues.OK
    defaults = signature()[1]
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
    )
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)
    do_logout = accepted['logout'][-1].lower() in ('true', '1')

    # sub-container inside default IU container
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
        <div class="global-full-height row">
            <div class="col-12 align-self-center">
    '''
    })

    output_objects.append({'object_type': 'header', 'text': 'Logout'})
    (oid_db, identity) = extract_client_openid(configuration,
                                               environ,
                                               lookup_dn=False)
    logger.info("%s from %s with identity %s" % (op_name, client_id, identity))
    if client_id and client_id == identity:
        output_objects.append({
            'object_type':
            'warning',
            'text':
            """You're accessing %s with a user certificate so to completely
logout you need to make sure it is protected by a password and then close the
browser. Please refer to your browser and system documentation for details.
""" % configuration.short_title
        })
        return (output_objects, status)

    # OpenID requires logout on provider and in local mod-auth-openid database.
    # IMPORTANT: some browsers like Firefox may inadvertently renew the local
    # OpenID session while loading the resources for this page (in parallel).
    # User clicks logout at OpenID provider, which sends her back here to
    # finish the local logout.

    if do_logout:
        if configuration.site_enable_twofactor:
            real_user = client_id
            addr_filter = environ['REMOTE_ADDR']
            # GDP logout is for project user so we strip project to force
            # repeat 2FA login on project logout / switch
            if configuration.site_enable_gdp:
                real_user = get_client_id_from_project_client_id(
                    configuration, client_id)
                addr_filter = None
            if real_user and not expire_twofactor_session(
                    configuration,
                    real_user,
                    environ,
                    allow_missing=True,
                    user_addr=addr_filter):
                logger.warning("expire twofactor session failed for %s" %
                               client_id)
                output_objects.append({
                    'object_type':
                    'html_form',
                    'text':
                    """<p class='warningtext'>
There was a potential problem with 2-factor session termination. Please contact
the %s Admins if it happens repeatedly.
</p>""" % configuration.short_title
                })
        logger.info("expiring active sessions for %s in %s" %
                    (identity, oid_db))
        (success, _) = expire_oid_sessions(configuration, oid_db, identity)
        logger.info("verifying no active sessions left for %s" % identity)
        (found, remaining) = find_oid_sessions(configuration, oid_db, identity)
        if success and found and not remaining:
            if configuration.site_enable_gdp:
                reentry_page = "https://%s" % configuration.server_fqdn
                if configuration.user_mig_oid_provider and \
                        identity.startswith(
                            configuration.user_mig_oid_provider):
                    reentry_page = configuration.migserver_https_mig_oid_url
                elif configuration.user_ext_oid_provider and \
                        identity.startswith(
                            configuration.user_ext_oid_provider):
                    reentry_page = configuration.migserver_https_ext_oid_url
                project_logout(configuration, 'https', environ['REMOTE_ADDR'],
                               client_id)
                html = '''
                <a id='gdp_logout' href='%s'></a>
                <script type='text/javascript'>
                    document.getElementById('gdp_logout').click();
                </script>''' % reentry_page
                output_objects.append({
                    'object_type': 'html_form',
                    'text': html
                })
            else:
                output_objects.append({
                    'object_type':
                    'text',
                    'text':
                    """You are now logged out of %s
    locally - you may want to close your web browser to finish""" %
                    configuration.short_title
                })
                title_entry = find_entry(output_objects, 'title')
                title_entry['skipmenu'] = True
        else:
            logger.error("remaining active sessions for %s: %s" %
                         (identity, remaining))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                "Could not log you out of %s!" % configuration.short_title
            })
            status = returnvalues.CLIENT_ERROR
    else:
        local_logout = '?logout=true'
        oid_logout = os.path.join(os.path.dirname(os.path.dirname(identity)),
                                  'logout?return_to=%(SCRIPT_URI)s' % environ)
        oid_logout += local_logout
        output_objects.append({
            'object_type':
            'text',
            'text':
            """Are you sure you want to
log out of %s?""" % configuration.short_title
        })
        output_objects.append({'object_type': 'text', 'text': ""})
        output_objects.append({
            'object_type': 'link',
            'destination': oid_logout,
            'class': 'genericbutton greenBtn',
            'text': "Yes"
        })
        output_objects.append({
            'object_type': 'link',
            'destination': 'javascript:history.back();',
            'class': 'genericbutton greenBtn',
            'text': "No, go back"
        })
    # sub-container end
    output_objects.append({
        'object_type': 'html_form',
        'text': '''
            </div>
        </div>
    '''
    })

    return (output_objects, status)
Esempio n. 2
0
def validate_input_and_cert(
    user_arguments_dict,
    defaults,
    output_objects,
    client_id,
    configuration,
    allow_rejects,
    require_user=True,
    filter_values=None,
    environ=None,
    ):
    """A wrapper used by most back end functionality - redirects to sign up
    if client_id is missing.
    """

    logger = configuration.logger
    if environ is None:
        environ = os.environ
    creds_error = ''
    if not client_id:
        creds_error = "Invalid or missing user credentials"
    elif require_user and not is_user(client_id, configuration.mig_server_home):
        creds_error = "No such user (%s)" % client_id

    if creds_error and not requested_page().endswith('logout.py'):
        output_objects.append({'object_type': 'error_text', 'text'
                              : creds_error
                              })

        # Redirect to sign-up cert page trying to guess relevant choices

        signup_url = os.path.join(configuration.migserver_https_sid_url,
                                  'cgi-sid', 'signup.py')
        signup_query = ''

        if not client_id:
            output_objects.append(
                {'object_type': 'text', 'text': '''Apparently you do not
already have access to %s, but you can sign up:''' % configuration.short_title
                 })
            output_objects.append({'object_type': 'link', 'text': signup_url,
                                   'destination': signup_url + signup_query})
            output_objects.append(
                {'object_type': 'text', 'text': '''If you already signed up and
received a user certificate you probably just need to import it in your
browser.'''})
        else:
            output_objects.append(
                {'object_type': 'text', 'text': '''Apparently you already have
suitable credentials and just need to sign up for a local %s account on:''' % \
                 configuration.short_title})

            if extract_client_cert(configuration, environ) is None:
                # Force logout/expire session cookie here to support signup
                identity = extract_client_openid(configuration, environ,
                                                 lookup_dn=False)
                if identity:
                    logger.info("expire openid user %s" % identity)
                    (success, _) = expire_oid_sessions(configuration, identity)
                else:
                    logger.info("no openid user logged in")
             
            output_objects.append({'object_type': 'link', 'text': signup_url,
                                   'destination': signup_url + signup_query})
        return (False, output_objects)

    (status, retval) = validate_input(user_arguments_dict, defaults,
            output_objects, allow_rejects, filter_values)

    return (status, retval)
Esempio n. 3
0
def validate_input_and_cert(
    user_arguments_dict,
    defaults,
    output_objects,
    client_id,
    configuration,
    allow_rejects,
    require_user=True,
    filter_values=None,
    environ=None,
):
    """A wrapper used by most back end functionality - redirects to sign up
    if client_id is missing.
    """

    logger = configuration.logger
    if environ is None:
        environ = os.environ
    creds_error = ''
    if not client_id:
        creds_error = "Invalid or missing user credentials"
    elif require_user and not is_user(client_id,
                                      configuration.mig_server_home):
        creds_error = "No such user (%s)" % client_id

    if creds_error and not requested_page().endswith('logout.py'):
        output_objects.append({
            'object_type': 'error_text',
            'text': creds_error
        })

        if configuration.site_enable_gdp:
            main_url = configuration.migserver_http_url
            output_objects.append({
                'object_type':
                'text',
                'text':
                '''Apparently you do not
                        have access to this page, please return to:'''
            })

            output_objects.append({
                'object_type': 'link',
                'text': main_url,
                'destination': main_url
            })
        else:
            # Redirect to sign-up cert page trying to guess relevant choices

            signup_url = os.path.join(configuration.migserver_https_sid_url,
                                      'cgi-sid', 'signup.py')
            signup_query = ''

            if not client_id:
                output_objects.append({
                    'object_type':
                    'text',
                    'text':
                    '''Apparently you do not
    already have access to %s, but you can sign up:''' %
                    configuration.short_title
                })
                output_objects.append({'object_type': 'link', 'text':
                                       '%s sign up page' % \
                                       configuration.short_title,
                                       'destination': signup_url + signup_query})
                output_objects.append({
                    'object_type':
                    'text',
                    'text':
                    '''If you already signed up and
    received a user certificate you probably just need to import it in your
    browser.'''
                })
            else:
                output_objects.append({
                    'object_type':
                    'text',
                    'text':
                    '''Apparently you already have
    suitable credentials and just need to sign up for a local %s account on the'''
                    % configuration.short_title
                })

                base_url = extract_base_url(configuration, environ)
                if base_url == configuration.migserver_https_ext_cert_url and \
                       'extcert' in configuration.site_login_methods:
                    signup_query = '?show=extcert'
                elif base_url in (configuration.migserver_https_ext_oid_url,
                                  configuration.migserver_https_mig_oid_url):
                    # Force logout/expire session cookie here to support signup
                    (oid_db, identity) = extract_client_openid(configuration,
                                                               environ,
                                                               lookup_dn=False)
                    if oid_db and identity:
                        logger.info("openid expire user %s in %s" %
                                    (identity, oid_db))
                        (success,
                         _) = expire_oid_sessions(configuration, oid_db,
                                                  identity)
                        if oid_db == auth_openid_ext_db and \
                               'extoid' in configuration.site_signup_methods:
                            signup_query = '?show=extoid'
                        else:
                            logger.error("unknown migoid client_id %s on %s" \
                                         % (client_id, base_url))
                else:
                    logger.warning("unexpected client_id %s on %s" % \
                                   (client_id, base_url))

                output_objects.append({'object_type': 'link', 'text':
                                       '%s sign up page' % \
                                       configuration.short_title,
                                       'destination':
                                       signup_url + signup_query})
        return (False, output_objects)

    (status, retval) = validate_input(user_arguments_dict, defaults,
                                      output_objects, allow_rejects,
                                      filter_values)

    return (status, retval)
Esempio n. 4
0
def main(client_id, user_arguments_dict, environ=None):
    """Main function used by front end"""

    if environ is None:
        environ = os.environ
    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False, op_menu=False)
    logger = configuration.logger
    logger.info('%s: args: %s' % (op_name, user_arguments_dict))
    prefilter_map = {}
    
    output_objects.append({'object_type': 'header', 'text'
                          : 'Automatic %s sign up' % \
                            configuration.short_title })
    identity = extract_client_openid(configuration, environ, lookup_dn=False)
    if client_id and client_id == identity:
        login_type = 'cert'
        base_url = configuration.migserver_https_cert_url
    elif identity:
        login_type = 'oid'
        base_url = configuration.migserver_https_oid_url
        for name in ('openid.sreg.cn', 'openid.sreg.fullname',
                     'openid.sreg.full_name'):
            prefilter_map[name] = filter_commonname
    else:
        output_objects.append(
            {'object_type': 'error_text', 'text': 'Missing user credentials'})
        return (output_objects, returnvalues.CLIENT_ERROR)
    defaults = signature(login_type)[1]
    (validate_status, accepted) = validate_input(
        user_arguments_dict, defaults, output_objects, allow_rejects=False,
        prefilter_map=prefilter_map)
    if not validate_status:
        logger.warning('%s invalid input: %s' % (op_name, accepted))
        return (accepted, returnvalues.CLIENT_ERROR)

    logger.debug('Accepted arguments: %s' % accepted)

    # Unfortunately OpenID redirect does not use POST
    if login_type != 'oid' and not correct_handler('POST'):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : 'Only accepting POST requests to prevent unintended updates'})
        return (output_objects, returnvalues.CLIENT_ERROR)

    admin_email = configuration.admin_email
    openid_names, oid_extras = [], {}

    # Extract raw values
    if login_type == 'cert':
        uniq_id = accepted['cert_id'][-1].strip()
        raw_name = accepted['cert_name'][-1].strip()
        country = accepted['country'][-1].strip()
        state = accepted['state'][-1].strip()
        org = accepted['org'][-1].strip()
        org_unit = ''
        role = ','.join([i for i in accepted['role'] if i])
        locality = ''
        timezone = ''
        email = accepted['email'][-1].strip()
        raw_login = None
    elif login_type == 'oid':
        uniq_id = accepted['openid.sreg.nickname'][-1].strip() or \
                   accepted['openid.sreg.short_id'][-1].strip()
        raw_name = accepted['openid.sreg.fullname'][-1].strip() or \
                    accepted['openid.sreg.full_name'][-1].strip()
        country = accepted['openid.sreg.country'][-1].strip()
        state = accepted['openid.sreg.state'][-1].strip()
        org = accepted['openid.sreg.o'][-1].strip() or \
              accepted['openid.sreg.organization'][-1].strip()
        org_unit = accepted['openid.sreg.ou'][-1].strip() or \
                   accepted['openid.sreg.organizational_unit'][-1].strip()
        # We may receive multiple roles
        role = ','.join([i for i in accepted['openid.sreg.role'] if i])
        locality = accepted['openid.sreg.locality'][-1].strip()
        timezone = accepted['openid.sreg.timezone'][-1].strip()
        email = accepted['openid.sreg.email'][-1].strip()

    # Fix case of values:
    # force name to capitalized form (henrik karlsen -> Henrik Karlsen)
    # please note that we get utf8 coded bytes here and title() treats such
    # chars as word termination. Temporarily force to unicode.
    try:
        full_name = force_utf8(force_unicode(raw_name).title())
    except Exception:
        logger.warning("could not use unicode form to capitalize full name")
        full_name = raw_name.title()
    country = country.upper()
    state = state.upper()
    email = email.lower()

    if login_type == 'oid':
        # Remap some oid attributes if on kit format with faculty in
        # organization and institute in organizational_unit. We can add them
        # as different fields as long as we make sure the x509 fields are
        # preserved.
        # We do that to allow autocreate updating existing cert users.
        
        if org_unit not in ('', 'NA'):
            org_unit = org_unit.upper()
            oid_extras['faculty'] = org
            oid_extras['institute'] = org_unit
            org = org_unit.upper()
            org_unit = 'NA'

        # Stay on virtual host - extra useful while we test dual OpenID
        base_url = environ.get('REQUEST_URI',
                               base_url).split('?')[0].replace('autocreate',
                                                               'fileman')
        raw_login = None
        for oid_provider in configuration.user_openid_providers:
            openid_prefix = oid_provider.rstrip('/') + '/'
            if identity.startswith(openid_prefix):
                raw_login = identity.replace(openid_prefix, '')
                break

    if raw_login:
        openid_names.append(raw_login)

    # we should have the proxy file read...
    proxy_content = accepted['proxy_upload'][-1]

    # keep comment to a single line

    comment = accepted['comment'][-1].replace('\n', '   ')

    # single quotes break command line format - remove

    comment = comment.replace("'", ' ')

    user_dict = {
        'short_id': uniq_id,
        'full_name': full_name,
        'organization': org,
        'organizational_unit': org_unit,
        'locality': locality,
        'state': state,
        'country': country,
        'email': email,
        'role': role,
        'timezone': timezone,
        'password': '',
        'comment': '%s: %s' % ('Existing certificate', comment),
        'openid_names': openid_names,
        }
    user_dict.update(oid_extras)

    # We must receive some ID from the provider
    if not uniq_id and not email:
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : 'No ID information received!'})
        if accepted.get('openid.sreg.required', '') and \
               identity:
            # Stay on virtual host - extra useful while we test dual OpenID
            url = environ.get('REQUEST_URI',
                              base_url).split('?')[0].replace('autocreate',
                                                              'logout')
            output_objects.append(
                {'object_type': 'text', 'text': '''Please note that sign-up
for OpenID access does not work if you are already signed in with your OpenID
provider - and that appears to be the case now.
You probably have to reload this page after you explicitly '''})
            output_objects.append(        
                {'object_type': 'link', 'destination': url,
                 'target': '_blank', 'text': "Logout"
                 })
        return (output_objects, returnvalues.CLIENT_ERROR)

    if login_type == 'cert':
        user_dict['expire'] = int(time.time() + cert_valid_days * 24 * 60 * 60)
        try:
            distinguished_name_to_user(uniq_id)
            user_dict['distinguished_name'] = uniq_id
        except:
            output_objects.append({'object_type': 'error_text', 'text'
                                   : '''Illegal Distinguished name:
Please note that the distinguished name must be a valid certificate DN with
multiple "key=val" fields separated by "/".
'''})
            return (output_objects, returnvalues.CLIENT_ERROR)
    elif login_type == 'oid':
        user_dict['expire'] = int(time.time() + oid_valid_days * 24 * 60 * 60)
        fill_distinguished_name(user_dict)
        uniq_id = user_dict['distinguished_name']

    # If server allows automatic addition of users with a CA validated cert
    # we create the user immediately and skip mail
    
    if login_type == 'cert' and configuration.auto_add_cert_user or \
           login_type == 'oid' and configuration.auto_add_oid_user:
        fill_user(user_dict)

        logger.info('create user: %s' % user_dict)
        
        # Now all user fields are set and we can begin adding the user

        db_path = os.path.join(configuration.mig_server_home, user_db_filename)
        try:
            create_user(user_dict, configuration.config_file, 
                        db_path, ask_renew=False, default_renew=True)
            if configuration.site_enable_griddk and \
                   accepted['proxy_upload'] != ['']:
                # save the file, display expiration date
                proxy_out = handle_proxy(proxy_content, uniq_id, 
                                         configuration)
                output_objects.extend(proxy_out)
        except Exception, err:
            logger.error('create failed for %s: %s' % (uniq_id, err))
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : '''Could not create the user account for you:
Please report this problem to the grid administrators (%s).''' % \
                 admin_email})
            return (output_objects, returnvalues.SYSTEM_ERROR)

        output_objects.append({'object_type': 'html_form', 'text'
                                   : '''Created the user account for you -
please open <a href="%s">your personal page</a> to proceed using it.
''' % base_url})
        return (output_objects, returnvalues.OK)
Esempio n. 5
0
def main(client_id, user_arguments_dict, environ=None):
    """Main function used by front end"""

    if environ is None:
        environ = os.environ
    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)

    status = returnvalues.OK
    defaults = signature()[1]
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
        )
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)
    do_logout = accepted['logout'][-1].lower() in ('true', '1')

    output_objects.append({'object_type': 'header', 'text'
                          : 'Logout'})
    identity = extract_client_openid(configuration, environ, lookup_dn=False)
    logger.info("%s from %s with identity %s" % (op_name, client_id, identity))
    if client_id and client_id == identity:
        output_objects.append(
            {'object_type': 'warning', 'text':
             """You're accessing %s with a user certificate so to completely
logout you need to make sure it is protected by a password and then close the
browser. Please refer to your browser and system documentation for details.
""" % configuration.short_title})
        return (output_objects, status)

    # OpenID requires logout on provider and in local mod-auth-openid database.
    # IMPORTANT: some browsers like Firefox may inadvertently renew the local
    # OpenID session while loading the resources for this page (in parallel).
    # User clicks logout at OpenID provider, which sends her back here to
    # finish the local logout.

    if do_logout:
        logger.info("expiring active sessions for %s" % identity)
        (success, _) = expire_oid_sessions(configuration, identity)
        logger.info("verifying no active sessions left for %s" % identity)
        (found, remaining) = find_oid_sessions(configuration, identity)
        if success and found and not remaining:
            output_objects.append(
                {'object_type': 'text', 'text': """You are now logged out of %s
locally - you may want to close your web browser to finish""" % \
                 configuration.short_title})
        else:
            logger.error("remaining active sessions for %s: %s" % (identity,
                         remaining))
            output_objects.append({'object_type': 'error_text', 'text'
                                   : "Could not log you out of %s!" % \
                                   configuration.short_title})
            status = returnvalues.CLIENT_ERROR
    else:
        local_logout = '?logout=true'
        oid_logout = os.path.join(os.path.dirname(os.path.dirname(identity)),
                                  'logout?return_to=%(SCRIPT_URI)s' % environ)
        oid_logout += local_logout
        output_objects.append(
            {'object_type': 'text', 'text': """You can log out from your OpenID
identity provider and end the active %s session with the link below.""" % \
             configuration.short_title})
        # TODO: we could trigger this link automatically
        output_objects.append(        
            {'object_type': 'link', 'destination': oid_logout,
             'text': "Logout"})
    return (output_objects, status)
Esempio n. 6
0
def main(client_id, user_arguments_dict, environ=None):
    """Main function used by front end"""

    if environ is None:
        environ = os.environ
    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False,
                                  op_menu=False)
    logger = configuration.logger
    logger.info('%s: args: %s' % (op_name, user_arguments_dict))
    prefilter_map = {}

    output_objects.append({
        'object_type':
        'header',
        'text':
        'Automatic %s sign up' % configuration.short_title
    })
    (_, identity) = extract_client_openid(configuration,
                                          environ,
                                          lookup_dn=False)
    req_url = environ['SCRIPT_URI']
    if client_id and client_id == identity:
        login_type = 'cert'
        if req_url.startswith(configuration.migserver_https_mig_cert_url):
            base_url = configuration.migserver_https_mig_cert_url
        elif req_url.startswith(configuration.migserver_https_ext_cert_url):
            base_url = configuration.migserver_https_ext_cert_url
        else:
            logger.warning('no match for cert request URL: %s' % req_url)
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'No matching request URL: %s' % req_url
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)
    elif identity:
        login_type = 'oid'
        if req_url.startswith(configuration.migserver_https_mig_oid_url):
            base_url = configuration.migserver_https_mig_oid_url
        elif req_url.startswith(configuration.migserver_https_ext_oid_url):
            base_url = configuration.migserver_https_ext_oid_url
        else:
            logger.warning('no match for oid request URL: %s' % req_url)
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'No matching request URL: %s' % req_url
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)
        for name in ('openid.sreg.cn', 'openid.sreg.fullname',
                     'openid.sreg.full_name'):
            prefilter_map[name] = filter_commonname
    else:
        output_objects.append({
            'object_type': 'error_text',
            'text': 'Missing user credentials'
        })
        return (output_objects, returnvalues.CLIENT_ERROR)
    defaults = signature(login_type)[1]
    (validate_status, accepted) = validate_input(user_arguments_dict,
                                                 defaults,
                                                 output_objects,
                                                 allow_rejects=False,
                                                 prefilter_map=prefilter_map)
    if not validate_status:
        logger.warning('%s invalid input: %s' % (op_name, accepted))
        return (accepted, returnvalues.CLIENT_ERROR)

    logger.debug('Accepted arguments: %s' % accepted)

    # Unfortunately OpenID redirect does not use POST

    if login_type != 'oid' and not safe_handler(
            configuration, 'post', op_name, client_id,
            get_csrf_limit(configuration), accepted):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''Only
accepting CSRF-filtered POST requests to prevent unintended updates'''
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    admin_email = configuration.admin_email
    (openid_names, oid_extras) = ([], {})

    # Extract raw values

    if login_type == 'cert':
        uniq_id = accepted['cert_id'][-1].strip()
        raw_name = accepted['cert_name'][-1].strip()
        country = accepted['country'][-1].strip()
        state = accepted['state'][-1].strip()
        org = accepted['org'][-1].strip()
        org_unit = ''
        role = ','.join([i for i in accepted['role'] if i])
        association = ','.join([i for i in accepted['association'] if i])
        locality = ''
        timezone = ''
        email = accepted['email'][-1].strip()
        raw_login = None
    elif login_type == 'oid':
        uniq_id = accepted['openid.sreg.nickname'][-1].strip() \
            or accepted['openid.sreg.short_id'][-1].strip()
        raw_name = accepted['openid.sreg.fullname'][-1].strip() \
            or accepted['openid.sreg.full_name'][-1].strip()
        country = accepted['openid.sreg.country'][-1].strip()
        state = accepted['openid.sreg.state'][-1].strip()
        org = accepted['openid.sreg.o'][-1].strip() \
            or accepted['openid.sreg.organization'][-1].strip()
        org_unit = accepted['openid.sreg.ou'][-1].strip() \
            or accepted['openid.sreg.organizational_unit'][-1].strip()

        # We may receive multiple roles and associations

        role = ','.join([i for i in accepted['openid.sreg.role'] if i])
        association = ','.join(
            [i for i in accepted['openid.sreg.association'] if i])
        locality = accepted['openid.sreg.locality'][-1].strip()
        timezone = accepted['openid.sreg.timezone'][-1].strip()

        # We may encounter results without an email, fall back to uniq_id then

        email = accepted['openid.sreg.email'][-1].strip() or uniq_id

    # Fix case of values:
    # force name to capitalized form (henrik karlsen -> Henrik Karlsen)
    # please note that we get utf8 coded bytes here and title() treats such
    # chars as word termination. Temporarily force to unicode.

    try:
        full_name = force_utf8(force_unicode(raw_name).title())
    except Exception:
        logger.warning('could not use unicode form to capitalize full name')
        full_name = raw_name.title()
    country = country.upper()
    state = state.upper()
    email = email.lower()

    if login_type == 'oid':

        # Remap some oid attributes if on KIT format with faculty in
        # organization and institute in organizational_unit. We can add them
        # as different fields as long as we make sure the x509 fields are
        # preserved.
        # Additionally in the special case with unknown institute (ou=ukendt)
        # we force organization to KU to align with cert policies.
        # We do that to allow autocreate updating existing cert users.

        if org_unit not in ('', 'NA'):
            org_unit = org_unit.upper()
            oid_extras['faculty'] = org
            oid_extras['institute'] = org_unit
            org = org_unit.upper()
            org_unit = 'NA'
            if org == 'UKENDT':
                org = 'KU'
                logger.info('unknown affilition, set organization to %s' % org)

        # Stay on virtual host - extra useful while we test dual OpenID

        if configuration.site_enable_gdp:
            base_url = environ.get('REQUEST_URI',
                                   base_url).split('?')[0].replace(
                                       'autocreate', 'gdpman')
        else:
            base_url = environ.get('REQUEST_URI',
                                   base_url).split('?')[0].replace(
                                       'autocreate', 'fileman')
        raw_login = None
        for oid_provider in configuration.user_openid_providers:
            openid_prefix = oid_provider.rstrip('/') + '/'
            if identity.startswith(openid_prefix):
                raw_login = identity.replace(openid_prefix, '')
                break

    if raw_login:
        openid_names.append(raw_login)

    # we should have the proxy file read...

    proxy_content = accepted['proxy_upload'][-1]

    # keep comment to a single line

    comment = accepted['comment'][-1].replace('\n', '   ')

    # single quotes break command line format - remove

    comment = comment.replace("'", ' ')

    user_dict = {
        'short_id': uniq_id,
        'full_name': full_name,
        'organization': org,
        'organizational_unit': org_unit,
        'locality': locality,
        'state': state,
        'country': country,
        'email': email,
        'role': role,
        'association': association,
        'timezone': timezone,
        'password': '',
        'comment': '%s: %s' % ('Existing certificate', comment),
        'openid_names': openid_names,
    }
    user_dict.update(oid_extras)

    # We must receive some ID from the provider

    if not uniq_id and not email:
        if accepted.get('openid.sreg.required', '') and identity:
            output_objects.append({
                'object_type':
                'html_form',
                'text':
                '''<p class="spinner iconleftpad">
Auto log out first to avoid sign up problems ...
</p>'''
            })
            html = \
                """
            <a id='autologout' href='%s'></a>
            <script type='text/javascript'>
                document.getElementById('autologout').click();
            </script>""" \
                % openid_autologout_url(configuration, identity,
                    client_id, req_url, user_arguments_dict)
            output_objects.append({'object_type': 'html_form', 'text': html})
        return (output_objects, returnvalues.CLIENT_ERROR)

    auth = 'unknown'
    if login_type == 'cert':
        auth = 'extcert'
        user_dict['expire'] = int(time.time() + cert_valid_days * 24 * 60 * 60)
        try:
            distinguished_name_to_user(uniq_id)
            user_dict['distinguished_name'] = uniq_id
        except:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                '''Illegal Distinguished name:
Please note that the distinguished name must be a valid certificate DN with
multiple "key=val" fields separated by "/".
'''
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
    elif login_type == 'oid':
        auth = 'extoid'
        user_dict['expire'] = int(time.time() + oid_valid_days * 24 * 60 * 60)
        fill_distinguished_name(user_dict)
        uniq_id = user_dict['distinguished_name']

    # Save auth access method

    user_dict['auth'] = [auth]

    # If server allows automatic addition of users with a CA validated cert
    # we create the user immediately and skip mail

    if login_type == 'cert' and configuration.auto_add_cert_user \
        or login_type == 'oid' and configuration.auto_add_oid_user:
        fill_user(user_dict)

        logger.info('create user: %s' % user_dict)

        # Now all user fields are set and we can begin adding the user

        db_path = os.path.join(configuration.mig_server_home, user_db_filename)
        try:
            create_user(user_dict,
                        configuration.config_file,
                        db_path,
                        ask_renew=False,
                        default_renew=True)
            if configuration.site_enable_griddk \
                and accepted['proxy_upload'] != ['']:

                # save the file, display expiration date

                proxy_out = handle_proxy(proxy_content, uniq_id, configuration)
                output_objects.extend(proxy_out)
        except Exception, err:
            logger.error('create failed for %s: %s' % (uniq_id, err))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                '''Could not create the user account for you:
Please report this problem to the grid administrators (%s).''' % admin_email
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)

        logger.info('created user account for %s' % uniq_id)
        output_objects.append({
            'object_type':
            'html_form',
            'text':
            '''Created the user account for you -
please open <a href="%s">your personal page</a> to proceed using it.
''' % base_url
        })
        return (output_objects, returnvalues.OK)
Esempio n. 7
0
                     (unpacked_url, unpacked_query))
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''Only
accepting fully signed GET requests to prevent unintended redirects'''
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # NOTE: from this point its' safe to use unpacked_url and unpacked_query
    redirect_url, redirect_query_dict = unpacked_url, unpacked_query

    output_objects.append({'object_type': 'header', 'text': 'Auto logout'})
    (oid_db, identity) = extract_client_openid(configuration,
                                               environ,
                                               lookup_dn=False)
    logger.info('%s from %s with identity %s' % (op_name, client_id, identity))
    if client_id and client_id == identity:
        output_objects.append({'object_type': 'warning',
                              'text': \
            """You're accessing %s with a user certificate and should never
            end up at this auto logout page.
            Please refer to your browser and system documentation for details."""
                            % configuration.short_title})
        return (output_objects, returnvalues.CLIENT_ERROR)

    msg = 'Auto log out first to avoid '
    if redirect_url.find('autocreate') != -1:
        msg += 'sign up problems ...'
    else: