/** * Configuration function to select ident provider * Implements IdentType directive * * @param cp IronBee configuration parser * @param name Unused * @param p1 Select ident provider * @param p2 Optional. If set to "any", ident will be checked by all * available providers if the configured provider doesn't * identify. Expected to be used in "Log" mode. * @param dummy Unused * @return status */ static ib_status_t ident_type(ib_cfgparser_t *cp, const char *name, const char *p1, const char *p2, void *dummy) { ident_cfg_t *cfg; ib_status_t rc; ib_module_t *m; char *p; rc = ib_engine_module_get(cp->ib, MODULE_NAME_STR, &m); assert((rc == IB_OK) && (m != NULL)); rc = ib_context_module_config(ib_context_main(cp->ib), m, &cfg); assert((rc == IB_OK) && (cfg != NULL)); cfg->type = p = ib_mm_strdup(cp->mm, p1); assert(p != NULL); do { if (isupper(*p)) { *p = tolower(*p); } } while (*++p); if (p2 && !strcasecmp(p2, "any")) { cfg->accept_any = 1; } else { cfg->accept_any = 0; } return rc; }
/** * Configuration function to select what ident regime to operate * Implements IdentMode directive * * @param cp IronBee configuration parser * @param name Unused * @param p1 Select whether ident is "Off" (do nothing), * "Log" (Log user id or unidentified) or * "Require" (Log id and issue challenge if unidentified) * @param dummy Unused * @return OK, or EINVAL if p1 is unrecognized */ static ib_status_t ident_mode(ib_cfgparser_t *cp, const char *name, const char *p1, void *dummy) { ident_cfg_t *cfg; ib_status_t rc; ib_module_t *m; rc = ib_engine_module_get(cp->ib, MODULE_NAME_STR, &m); assert((rc == IB_OK) && (m != NULL)); rc = ib_context_module_config(ib_context_main(cp->ib), m, &cfg); assert((rc == IB_OK) && (cfg != NULL)); if (!strcasecmp(p1, "Off")) { cfg->mode = ident_off; } else if (!strcasecmp(p1, "Log")) { cfg->mode = ident_log; } else if (!strcasecmp(p1, "Require")) { cfg->mode = ident_require; } else { rc = IB_EINVAL; } return rc; }
/** * Access configuration data. * * @param[in] ib IronBee engine. * @return * - configuration on success. * - NULL on failure. */ static ee_config_t *ee_get_config( ib_engine_t *ib ) { assert(ib != NULL); ib_module_t *module; ib_context_t *context; ib_status_t rc; ee_config_t *config; rc = ib_engine_module_get(ib, MODULE_NAME_STR, &module); if (rc != IB_OK) { return NULL; } context = ib_context_main(ib); if (context == NULL) { return NULL; } rc = ib_context_module_config(context, module, &config); if (rc != IB_OK) { return NULL; } return config; }
/** * Create an instance of the @c ee_match_any operator. * * Looks up the automata name and adds the automata to the operator instance. * * @param[in] ctx Current context. * @param[in] parameters Automata name. * @param[out] instance_data Instance data. * @param[in] cbdata Callback data. */ static ib_status_t ee_match_any_operator_create( ib_context_t *ctx, const char *parameters, void *instance_data, void *cbdata ) { assert(ctx != NULL); assert(parameters != NULL); assert(instance_data != NULL); ib_status_t rc; ia_eudoxus_t* eudoxus; ee_operator_data_t *operator_data; ib_module_t *module; ib_engine_t *ib = ib_context_get_engine(ctx); ib_mpool_t *pool = ib_context_get_mpool(ctx); const ee_config_t *config = ee_get_config(ib); const ib_hash_t *eudoxus_pattern_hash; assert(config != NULL); assert(config->eudoxus_pattern_hash != NULL); /* Get my module object */ rc = ib_engine_module_get(ib, MODULE_NAME_STR, &module); if (rc != IB_OK) { ib_log_error(ib, "Failed to get eudoxus operator module object: %s", ib_status_to_string(rc)); return rc; } /* Allocate a rule data object, populate it */ operator_data = ib_mpool_alloc(pool, sizeof(*operator_data)); if (operator_data == NULL) { return IB_EALLOC; } eudoxus_pattern_hash = config->eudoxus_pattern_hash; rc = ib_hash_get(eudoxus_pattern_hash, &eudoxus, parameters); if (rc == IB_ENOENT ) { ib_log_error(ib, MODULE_NAME_STR ": No eudoxus automata named %s found.", parameters); return rc; } else if (rc != IB_OK) { ib_log_error(ib, MODULE_NAME_STR ": Error setting up eudoxus automata operator."); return rc; } operator_data->eudoxus = eudoxus; *(ee_operator_data_t **)instance_data = operator_data; ib_log_debug(ib, "Found compiled eudoxus pattern \"%s\"", parameters); return IB_OK; }
/** * Handle on/off directives. * * @param[in] cp Config parser * @param[in] name Directive name * @param[in] onoff on/off flag * @param[in] cbdata Callback data (ignored) * * @returns Status code */ static ib_status_t handle_directive_onoff(ib_cfgparser_t *cp, const char *name, int onoff, void *cbdata) { assert(cp != NULL); assert(name != NULL); assert(cp->ib != NULL); ib_engine_t *ib = cp->ib; ib_status_t rc; ib_module_t *module = NULL; modpcre_cfg_t *config = NULL; ib_context_t *ctx = cp->cur_ctx ? cp->cur_ctx : ib_context_main(ib); const char *pname; /* Get my module object */ rc = ib_engine_module_get(cp->ib, MODULE_NAME_STR, &module); if (rc != IB_OK) { ib_cfg_log_error(cp, "Failed to get %s module object: %s", MODULE_NAME_STR, ib_status_to_string(rc)); return rc; } /* Get my module configuration */ rc = ib_context_module_config(ctx, module, (void *)&config); if (rc != IB_OK) { ib_cfg_log_error(cp, "Failed to get %s module configuration: %s", MODULE_NAME_STR, ib_status_to_string(rc)); return rc; } if (strcasecmp("PcreStudy", name) == 0) { pname = MODULE_NAME_STR ".study"; } else if (strcasecmp("PcreUseJit", name) == 0) { pname = MODULE_NAME_STR ".use_jit"; } else { ib_cfg_log_error(cp, "Unhandled directive \"%s\"", name); return IB_EINVAL; } rc = ib_context_set_num(ctx, pname, onoff); if (rc != IB_OK) { ib_cfg_log_error(cp, "Failed to set \"%s\" to %s for \"%s\": %s", pname, onoff ? "true" : "false", name, ib_status_to_string(rc)); } return IB_OK; }
/** * Function exported to enable a module to register an ident provider * * @param engine Engine to register with * @param name Provider name (referenced in IdentType directive) * @param provider The identity provider * @return status */ ib_status_t ib_ident_provider_register(ib_engine_t *engine, const char *name, ib_ident_provider_t *provider) { ident_cfg_t *cfg; ib_status_t rc; ib_module_t *m; rc = ib_engine_module_get(engine, MODULE_NAME_STR, &m); assert((rc == IB_OK) && (m != NULL)); rc = ib_context_module_config(ib_context_main(engine), m, &cfg); assert((rc == IB_OK) && (cfg != NULL)); if (cfg->providers == NULL) { rc = ib_hash_create(&cfg->providers, ib_engine_mm_main_get(engine)); assert((rc == IB_OK) && (cfg->providers != NULL)); } return ib_hash_set(cfg->providers, name, provider); }
/** * Create the PCRE operator. * * @param[in] ctx Current context. * @param[in] parameters Unparsed string with the parameters to * initialize the operator instance. * @param[out] instance_data Instance data. * @param[in] cbdata Callback data. * * @returns IB_OK on success or IB_EALLOC on any other type of error. */ static ib_status_t dfa_operator_create( ib_context_t *ctx, const char *parameters, void *instance_data, void *cbdata ) { assert(ctx != NULL); assert(parameters != NULL); assert(instance_data != NULL); ib_engine_t *ib = ib_context_get_engine(ctx); ib_mpool_t *pool = ib_context_get_mpool(ctx); assert(ib != NULL); assert(pool != NULL); modpcre_cpat_data_t *cpdata; modpcre_operator_data_t *operator_data; ib_module_t *module; modpcre_cfg_t *config; ib_status_t rc; const char *errptr; int erroffset; /* Get my module object */ rc = ib_engine_module_get(ib, MODULE_NAME_STR, &module); if (rc != IB_OK) { ib_log_error(ib, "Failed to get pcre module object: %s", ib_status_to_string(rc)); return rc; } /* Get the context configuration */ rc = ib_context_module_config(ctx, module, &config); if (rc != IB_OK) { ib_log_error(ib, "Failed to get pcre module configuration: %s", ib_status_to_string(rc)); return rc; } rc = pcre_compile_internal(ib, pool, config, true, &cpdata, parameters, &errptr, &erroffset); if (rc != IB_OK) { ib_log_error(ib, "Failed to parse DFA operator pattern \"%s\":%s", parameters, ib_status_to_string(rc)); return rc; } /* Allocate a rule data object, populate it */ operator_data = ib_mpool_alloc(pool, sizeof(*operator_data)); if (operator_data == NULL) { return IB_EALLOC; } operator_data->cpdata = cpdata; rc = dfa_id_set(pool, operator_data); if (rc != IB_OK) { ib_log_error(ib, "Error creating ID for DFA: %s", ib_status_to_string(rc)); return rc; } ib_log_debug(ib, "Compiled DFA id=\"%s\" operator pattern \"%s\" @ %p", operator_data->id, parameters, (void *)cpdata->cpatt); *(modpcre_operator_data_t **)instance_data = operator_data; return IB_OK; }
/** * Create the PCRE operator. * * @param[in] ctx Current context. * @param[in] parameters Unparsed string with the parameters to * initialize the operator instance. * @param[out] instance_data Instance data. * @param[in] cbdata Callback data. * * @returns IB_OK on success or IB_EALLOC on any other type of error. */ static ib_status_t pcre_operator_create( ib_context_t *ctx, const char *parameters, void *instance_data, void *cbdata ) { assert(ctx != NULL); assert(parameters != NULL); assert(instance_data != NULL); ib_engine_t *ib = ib_context_get_engine(ctx); ib_mpool_t *pool = ib_context_get_mpool(ctx); assert(ib != NULL); assert(pool != NULL); modpcre_cpat_data_t *cpdata = NULL; modpcre_operator_data_t *operator_data = NULL; ib_module_t *module; modpcre_cfg_t *config; ib_status_t rc; const char *errptr; int erroffset; if (parameters == NULL) { ib_log_error(ib, "No pattern for operator"); return IB_EINVAL; } /* Get my module object */ rc = ib_engine_module_get(ib, MODULE_NAME_STR, &module); if (rc != IB_OK) { ib_log_error(ib, "Failed to get pcre module object: %s", ib_status_to_string(rc)); return rc; } /* Get the context configuration */ rc = ib_context_module_config(ctx, module, &config); if (rc != IB_OK) { ib_log_error(ib, "Failed to get pcre module configuration: %s", ib_status_to_string(rc)); return rc; } /* Compile the pattern. Note that the rule data is an alias for * the compiled pattern type */ rc = pcre_compile_internal(ib, pool, config, false, &cpdata, parameters, &errptr, &erroffset); if (rc != IB_OK) { return rc; } /* Allocate a rule data object, populate it */ operator_data = ib_mpool_alloc(pool, sizeof(*operator_data)); if (operator_data == NULL) { return IB_EALLOC; } operator_data->cpdata = cpdata; operator_data->id = NULL; /* Not needed for rx rules */ /* Rule data is an alias for the compiled pattern data */ *(modpcre_operator_data_t **)instance_data = operator_data; return rc; }
/** * Handle single parameter directives. * * @param cp Config parser * @param name Directive name * @param p1 First parameter * @param cbdata Callback data (from directive registration) * * @returns Status code */ static ib_status_t handle_directive_param(ib_cfgparser_t *cp, const char *name, const char *p1, void *cbdata) { assert(cp != NULL); assert(name != NULL); assert(p1 != NULL); assert(cp->ib != NULL); ib_engine_t *ib = cp->ib; ib_status_t rc; ib_module_t *module = NULL; modpcre_cfg_t *config = NULL; ib_context_t *ctx = cp->cur_ctx ? cp->cur_ctx : ib_context_main(ib); const char *pname; ib_num_t value; /* Get my module object */ rc = ib_engine_module_get(cp->ib, MODULE_NAME_STR, &module); if (rc != IB_OK) { ib_cfg_log_error(cp, "Failed to get %s module object: %s", MODULE_NAME_STR, ib_status_to_string(rc)); return rc; } /* Get my module configuration */ rc = ib_context_module_config(ctx, module, (void *)&config); if (rc != IB_OK) { ib_cfg_log_error(cp, "Failed to get %s module configuration: %s", MODULE_NAME_STR, ib_status_to_string(rc)); return rc; } /* p1 should be a number */ rc = ib_string_to_num(p1, 0, &value); if (rc != IB_OK) { ib_cfg_log_error(cp, "Failed to convert \"%s\" to a number for \"%s\": %s", p1, name, ib_status_to_string(rc)); return rc; } if (strcasecmp("PcreMatchLimit", name) == 0) { pname = "pcre.match_limit"; } else if (strcasecmp("PcreMatchLimitRecursion", name) == 0) { pname = "pcre.match_limit_recursion"; } else if (strcasecmp("PcreJitStackStart", name) == 0) { pname = "pcre.jit_stack_start"; } else if (strcasecmp("PcreJitStackMax", name) == 0) { pname = "pcre.jit_stack_max"; } else if (strcasecmp("PcreDfaWorkspaceSize", name) == 0) { pname = "pcre.dfa_workspace_size"; } else { ib_cfg_log_error(cp, "Unhandled directive \"%s\"", name); return IB_EINVAL; } rc = ib_context_set_num(ctx, pname, value); if (rc != IB_OK) { ib_cfg_log_error(cp, "Failed to set \"%s\" to %ld for \"%s\": %s", pname, (long int)value, name, ib_status_to_string(rc)); } return IB_OK; }
/** * Main identity handler. Called both on request_header_finished and * request_finished: the configured provider decides which state to * run on, and skips (returns immediately) on the other state. * * If configured mode is "Off", just returns. Otherwise calls provider's * check_id function to check and log user ID. Optionally cycles through * other providers. Finally, if client is not identified and mode is * "Require", calls provider's challenge function to ask client to * identify (e.g. HTTP 401). * * @param ib The engine * @param tx The transaction * @param state State that triggered the call * @param cbdata Unused */ static ib_status_t ident_handler(ib_engine_t *ib, ib_tx_t *tx, ib_state_t state, void *cbdata) { ident_cfg_t *cfg; const char *userid = NULL; ib_ident_provider_t *provider; ib_status_t rc; ib_module_t *m; assert(state == request_header_finished_state || state == request_finished_state); rc = ib_engine_module_get(ib, MODULE_NAME_STR, &m); assert((rc == IB_OK) && (m != NULL)); rc = ib_context_module_config(ib_context_main(ib), m, &cfg); assert((rc == IB_OK) && (cfg != NULL)); if (cfg->mode == ident_off) { return IB_OK; } if (cfg->type != NULL && cfg->providers != NULL) { rc = ib_hash_get(cfg->providers, &provider, cfg->type); if (rc != IB_OK || provider == NULL) { ib_log_error_tx(tx, "Identifier '%s' configured but not available", cfg->type); provider = &ident_dummy_provider; } } else { ib_log_error_tx(tx, "Ident module loaded but not configured!"); provider = &ident_dummy_provider; } if (provider->state != state) { /* This provider doesn't check now */ return IB_OK; } /* OK, ident is on. Verify if there is a user ID */ userid = provider->check_id(tx); if (userid == NULL && cfg->accept_any && cfg->providers != NULL) { ib_hash_iterator_t *iterator = ib_hash_iterator_create(tx->mm); ib_ident_provider_t *p; for (ib_hash_iterator_first(iterator, cfg->providers); !userid && !ib_hash_iterator_at_end(iterator); ib_hash_iterator_next(iterator)) { ib_hash_iterator_fetch(NULL, NULL, &p, iterator); /* configured provider already checked - so skip it now */ if (p->check_id != provider->check_id) { userid = p->check_id(tx); } } } if (userid != NULL) { ib_log_info(ib, "User identified as %s", userid); return IB_OK; } /* If we haven't configured an ident type, don't enforce */ if (cfg->type == NULL) { return IB_OK; } /* If we're enforcing ident, send a challenge */ return provider->challenge(tx); }
static ib_status_t sqli_dir_fingerprint_set( ib_cfgparser_t *cp, const char *directive_name, const char *set_name, const char *set_path, void *cbdata ) { assert(cp != NULL); assert(directive_name != NULL); assert(set_name != NULL); assert(set_path != NULL); ib_status_t rc; ib_context_t *ctx = NULL; ib_module_t *m = NULL; sqli_module_config_t *cfg = NULL; sqli_fingerprint_set_t *ps = NULL; ib_mm_t mm; char *abs_set_path = NULL; rc = ib_cfgparser_context_current(cp, &ctx); assert(rc == IB_OK); assert(ctx != NULL); if (ctx != ib_context_main(cp->ib)) { ib_cfg_log_error(cp, "%s: Only valid at main context.", directive_name ); return IB_EINVAL; } if (strcmp("default", set_name) == 0) { ib_cfg_log_error(cp, "%s: default is a reserved set name.", directive_name ); return IB_EINVAL; } mm = ib_engine_mm_main_get(cp->ib); rc = ib_engine_module_get( ib_context_get_engine(ctx), MODULE_NAME_STR, &m ); assert(rc == IB_OK); rc = ib_context_module_config(ctx, m, &cfg); assert(rc == IB_OK); if (cfg->fingerprint_sets == NULL) { rc = ib_hash_create(&cfg->fingerprint_sets, mm); assert(rc == IB_OK); } assert(cfg->fingerprint_sets != NULL); rc = ib_hash_get(cfg->fingerprint_sets, NULL, set_name); if (rc == IB_OK) { ib_cfg_log_error(cp, "%s: Duplicate fingerprint set definition: %s", directive_name, set_name ); return IB_EINVAL; } assert(rc == IB_ENOENT); abs_set_path = ib_util_relative_file( ib_engine_mm_config_get(cp->ib), ib_cfgparser_curr_file(cp), set_path ); if (abs_set_path == NULL) { return IB_EALLOC; } rc = sqli_create_fingerprint_set_from_file(&ps, abs_set_path, mm); if (rc != IB_OK) { ib_cfg_log_error(cp, "%s: Failure to load fingerprint set from file: %s", directive_name, abs_set_path ); return IB_EINVAL; } assert(ps != NULL); rc = ib_hash_set(cfg->fingerprint_sets, ib_mm_strdup(mm, set_name), ps); assert(rc == IB_OK); return IB_OK; }