Esempio n. 1
0
def _get_local_config(config_filename=None, apply_overrides=True):
    """
    Load local config file optionally specified by 'config_filename'

    Args: See get_config
    Returns: A ConfigProvider object
    """
    try:
        if not config_filename:
            root = util.get_home_dir()
            config_filename = os.path.join(root, 'conf', 'authproxy.cfg')
        # open configfile and construct ConfigProvider
        with open(config_filename, "r") as config_file:
            configuration = ConfigProvider.from_ini_file(
                config_file, os.path.abspath(config_filename), apply_overrides)
    except IOError:
        raise ConfigError(
            'Config file missing or unreadable: {0}'.format(config_filename))

    return configuration
Esempio n. 2
0
 def __init__(self, args):
     win32serviceutil.ServiceFramework.__init__(self, args)
     self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
     self.duo_root = util.get_home_dir()
Esempio n. 3
0
def create_application(args=None, twistd_user=None, log_group=None):
    home_dir = util.get_home_dir()
    os.chdir(home_dir)
    is_logging_insecure = False

    if syslog is not None:
        facility_dict = {
            'LOG_KERN': pySyslog.LOG_KERN,
            'LOG_USER': pySyslog.LOG_USER,
            'LOG_MAIL': pySyslog.LOG_MAIL,
            'LOG_DAEMON': pySyslog.LOG_DAEMON,
            'LOG_AUTH': pySyslog.LOG_AUTH,
            'LOG_LPR': pySyslog.LOG_LPR,
            'LOG_NEWS': pySyslog.LOG_NEWS,
            'LOG_UUCP': pySyslog.LOG_UUCP,
            'LOG_CRON': pySyslog.LOG_CRON,
            'LOG_SYSLOG': pySyslog.LOG_SYSLOG,
            'LOG_LOCAL0': pySyslog.LOG_LOCAL0,
            'LOG_LOCAL1': pySyslog.LOG_LOCAL1,
            'LOG_LOCAL2': pySyslog.LOG_LOCAL2,
            'LOG_LOCAL3': pySyslog.LOG_LOCAL3,
            'LOG_LOCAL4': pySyslog.LOG_LOCAL4,
            'LOG_LOCAL5': pySyslog.LOG_LOCAL5,
            'LOG_LOCAL6': pySyslog.LOG_LOCAL6,
            'LOG_LOCAL7': pySyslog.LOG_LOCAL7
        }

    # parse command-line args, if appropriate
    primary_only_time = None
    if args:
        option_parser = argparse.ArgumentParser()

        option_parser.add_argument(
            "--primary-only", type=int, nargs='?',
            help="This option disables secondary authentication for the specified number of minutes (default 60)",
            default=None, const=60
        )
        option_parser.add_argument(
            "--logging-insecure",
            action="store_true",
            help="This option enables debug, and prints logs containing passwords and possibly other secrets.",
            default=False
        )
        options = option_parser.parse_args()
        is_logging_insecure = options.logging_insecure
        primary_only_time = options.primary_only

    config_filename = os.path.join('conf', 'authproxy.cfg')
    configuration = config_provider.get_config(config_filename)

    if primary_only_time is not None:
        if primary_only_time > 240:
            print("Primary only mode can only be enabled for a maximum of 4 hours (240 minutes)")
            sys.exit(2)
        else:
            PrimaryOnlyManager.enable_primary_only(primary_only_time)

    main_config = configuration.get_main_section_config()
    if main_config:
        log.msg('Main Configuration:')
        log.config(main_config)

    fips_mode = main_config.get_bool('fips_mode', False)
    if fips_mode:
        fips_manager.enable()

    # handle log configuration
    log_to_file = main_config.get_bool('log_file', False)
    log_stdout = main_config.get_bool('log_stdout', False)
    log_syslog = main_config.get_bool('log_syslog', False)
    log_auth_events = main_config.get_bool('log_auth_events', False)
    log_sso_events = main_config.get_bool('log_sso_events', True)

    if is_logging_insecure:
        globalLogPublisher.addObserver(textFileLogObserver(sys.stdout))
    else:
        if log_to_file or not (log_to_file or log_syslog or log_stdout):
            log_dir = main_config.get_str('log_dir', 'log')
            log_max_size = main_config.get_int('log_max_size', 10 * (1 << 20))
            log_max_files = main_config.get_int('log_max_files', 6)
            if log_max_files == 0:
                # we need to pass None explicitly if we want there to be no limit
                # 0 would just mean no logfiles would get kept...
                log_max_files = None

            log_file = create_log_file('authproxy.log', log_dir, log_max_size,
                                       log_max_files, twistd_user, log_group)
            log_file_observer = textFileLogObserver(log_file)

            if log_auth_events:
                auth_log_file = create_log_file('authevents.log', log_dir, log_max_size, log_max_files, twistd_user, log_group)
                auth_observer = FileLogObserver(auth_log_file, log.format_auth_event)
            else:
                auth_observer = log.no_op_observer

            if log_sso_events:
                sso_log_file = create_log_file('ssoevents.log', log_dir, log_max_size, log_max_files, twistd_user, log_group)
                sso_observer = FileLogObserver(sso_log_file, log.format_sso_event)
            else:
                sso_observer = log.no_op_observer

            auth_filtering_observer = FilteringLogObserver(auth_observer,
                                                           [log.auth_type_predicate],
                                                           log.no_op_observer)

            globalLogPublisher.addObserver(auth_filtering_observer)

            sso_filtering_observer = FilteringLogObserver(sso_observer,
                                                          [log.sso_type_predicate],
                                                          log.no_op_observer)

            globalLogPublisher.addObserver(sso_filtering_observer)

            # the default authproxy.log
            log_file_observer = FilteringLogObserver(log_file_observer,
                                                     [log.only_default_log_predicate],
                                                     log.no_op_observer)

            globalLogPublisher.addObserver(log_file_observer)

        if log_stdout:
            std_out_observer = textFileLogObserver(sys.stdout)
            std_out_filter = FilteringLogObserver(log.no_op_observer,
                                                  [log.auth_type_predicate],
                                                  std_out_observer)
            globalLogPublisher.addObserver(std_out_filter)
        if log_syslog:
            if syslog is None:
                raise config_error.ConfigError('syslog not supported on Windows')
            syslog_facilitystr = main_config.get_str('syslog_facility', 'LOG_USER')
            syslog_facility = facility_dict.get(syslog_facilitystr, None)
            if syslog_facility is None:
                raise config_error.ConfigError('Unknown syslog_facility: {0}'.format(syslog_facilitystr))
            syslog_observer = syslog.SyslogObserver('Authproxy', facility=syslog_facility)
            wrapped_syslog_observer = LegacyLogObserverWrapper(syslog_observer.emit)
            syslog_filtering_observer = FilteringLogObserver(log.no_op_observer,
                                                             [log.auth_type_predicate],
                                                             wrapped_syslog_observer)
            globalLogPublisher.addObserver(syslog_filtering_observer)

    # Global debug mode
    if is_logging_insecure:
        debug_mode = True
    else:
        debug_mode = main_config.get_bool('debug', False)

    http.set_debug(debug_mode)
    http.set_is_logging_insecure(is_logging_insecure)

    # Create main application.
    application = Application('duoauthproxy')
    LogReadyService().setServiceParent(application)

    fips_mode = fips_manager.status()
    if fips_mode:
        log.msg("FIPS mode {0} is enabled with {1}".format(fips_mode, fips_manager.get_openssl_version()))
    else:
        log.msg("FIPS mode is not enabled")

    # get ca certs file
    http_ca_certs_file = main_config.get_str('http_ca_certs_file', '')
    if http_ca_certs_file:
        http_ca_certs_file = util.resolve_file_path(http_ca_certs_file)
    else:
        http_ca_certs_file = os.path.join('conf', const.DEFAULT_HTTP_CERTS_FILE)

    # read ca certs
    if not os.path.isfile(http_ca_certs_file):
        http_ca_certs_file = os.path.join('conf', http_ca_certs_file)
    with open(http_ca_certs_file, 'r') as bundle_fp:
        http.set_ca_certs(ssl_verify.load_ca_bundle(bundle_fp))

    # get proxy settings
    http_proxy_host = main_config.get_str('http_proxy_host', '')
    http_proxy_port = main_config.get_int('http_proxy_port', 80)
    if http_proxy_host:
        http.set_proxy(http_proxy_host, http_proxy_port)

    sections = section.parse_sections(configuration, is_logging_insecure)
    module_factory = section.ModuleFactory(sections, application)
    modules_by_type = module_factory.make_modules()

    if not any(modules_by_type.values()):
        raise config_error.ConfigError('No integrations in config file.')

    # Setup forwarding/server pairs by port
    for port, interface in modules_by_type.get('server', []):
        server_networks = {}
        server_names = {}
        for section_name, server_module, server_config in modules_by_type['server'][(port, interface)]:
            client_name = configuration.get_section_client(section_name)

            if not client_name:
                if server_module.Module.no_client:
                    modules_by_type['client']['no_client'] = None
                    client_name = 'no_client'
                else:
                    raise config_error.ConfigError('Neither module %s or main has "client" value' % section_name)

            if section_name.startswith('ldap_server_auto') and not client_name.startswith('ad_client'):
                raise config_error.ConfigError('ad_client is required by ldap_server_auto. No ad_client found in config file. ')

            if client_name != 'radius_client' \
                    and server_config.get_str('pass_through_attr_names', ''):
                raise config_error.ConfigError('Can only pass through radius attributes if using a radius client')
            server_instance = server_module.Module(server_config,
                                                   modules_by_type['client'][client_name],
                                                   section_name)
            server_instance.setServiceParent(application)

            if section_name.startswith('radius_server_'):
                server_networks[server_instance] = parse_radius_secrets(server_config).keys()
                server_names[server_instance] = section_name

        if server_names:
            forward_module = forward_serv
            forward_instance = forward_module.Module(
                port=port,
                servers=server_networks,
                server_names=server_names,
                interface=interface,
                debug=debug_mode,
            )
            forward_instance.setServiceParent(application)

    # set user-agent
    sections = ','.join(sorted(set(configuration.list_sections())))
    user_agent = "duoauthproxy/{0} ({1}; Python{2}; {3})".format(
        get_version(),
        platform.platform(),
        platform.python_version(),
        sections)
    http.set_user_agent(user_agent)

    # Authproxy uses globalLogPublisher to emit events. Defining a no-op emitter will squelch the creation
    # of the unwatned twistd default logging mechanisms.
    def no_op_emitter(eventDict):
        pass

    application.setComponent(ILogObserver, no_op_emitter)

    return application