Exemple #1
0
void ib_vclog_ex(ib_context_t *ctx, int level,
                 const char *prefix, const char *file, int line,
                 const char *fmt, va_list ap)
{
    IB_FTRACE_INIT(ib_vclog_ex);
    IB_PROVIDER_API_TYPE(logger) *api;
    ib_core_cfg_t *corecfg;
    ib_provider_inst_t *pi = NULL;
    ib_status_t rc;
    char prefix_with_pid[1024];

    if (prefix != NULL) {
      snprintf(prefix_with_pid, 1024, "[%d] %s", getpid(), prefix);
    }
    else {
      snprintf(prefix_with_pid, 1024, "[%d] ", getpid());
    }

    if (ctx != NULL) {
        rc = ib_context_module_config(ctx, ib_core_module(),
                                      (void *)&corecfg);
        if (rc == IB_OK) {
            pi = corecfg->pi.logger;
        }

        if (pi != NULL) {
            api = (IB_PROVIDER_API_TYPE(logger) *)pi->pr->api;

            api->vlogmsg(pi, ctx, level, prefix_with_pid, file, line, fmt, ap);

            IB_FTRACE_RET_VOID();
        }
Exemple #2
0
/**
 * 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;
}
Exemple #3
0
void DLL_PUBLIC ib_vlog_ex(ib_engine_t *ib, int level,
                           const ib_tx_t *tx,
                           const char *prefix, const char *file, int line,
                           const char *fmt, va_list ap)
{
    IB_FTRACE_INIT();

    IB_PROVIDER_API_TYPE(logger) *api;
    ib_core_cfg_t *corecfg;
    ib_provider_inst_t *pi = NULL;
    ib_status_t rc;
    ib_context_t *ctx;

    ctx = ib_context_main(ib);

    if (ctx != NULL) {
        rc = ib_context_module_config(ctx, ib_core_module(),
                                      (void *)&corecfg);
        if (rc == IB_OK) {
            pi = corecfg->pi.logger;
        }

        if (pi != NULL) {
            api = (IB_PROVIDER_API_TYPE(logger) *)pi->pr->api;

            api->vlogmsg(pi, ctx, level, tx, prefix, file, line, fmt, ap);

            IB_FTRACE_RET_VOID();
        }
Exemple #4
0
/**
 * 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;
}
Exemple #5
0
/**
 * 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;
}
Exemple #6
0
static
ib_status_t sqli_op_create(
    ib_context_t *ctx,
    ib_mm_t       mm,
    const char   *parameters,
    void         *instance_data,
    void         *cbdata
)
{
    ib_engine_t *ib = ib_context_get_engine(ctx);
    ib_status_t rc;
    ib_module_t *m = (ib_module_t *)cbdata;
    const char *set_name;
    size_t set_name_len;

    const sqli_module_config_t *cfg = NULL;
    const sqli_fingerprint_set_t    *ps  = NULL;

    if (parameters == NULL) {
        ib_log_error(ib, "Missing parameter for operator sqli");
        return IB_EINVAL;
    }

    set_name = parameters;
    set_name_len = strlen(parameters);
    if (set_name[0] == '\'') {
        ++set_name;
        --set_name_len;
    }
    if (set_name[set_name_len-1] == '\'') {
        --set_name_len;
    }

    if (strncmp("default", set_name, set_name_len) == 0) {
        *(const sqli_fingerprint_set_t **)instance_data = NULL;
        return IB_OK;
    }

    rc = ib_context_module_config(ctx, m, &cfg);
    assert(rc == IB_OK);
    if (cfg->fingerprint_sets == NULL) {
        rc = IB_ENOENT;
    }
    else {
        rc = ib_hash_get_ex(cfg->fingerprint_sets, &ps, set_name, set_name_len);
    }
    if (rc == IB_ENOENT) {
        ib_log_error(ib, "No such fingerprint set: %s", parameters);
        return IB_EINVAL;
    }
    assert(rc == IB_OK);
    assert(ps != NULL);

    *(const sqli_fingerprint_set_t **)instance_data = ps;

    return IB_OK;
}
Exemple #7
0
ib_provider_inst_t *ib_log_provider_get_instance(ib_context_t *ctx)
{
    IB_FTRACE_INIT();
    ib_core_cfg_t *corecfg;
    ib_status_t rc;

    rc = ib_context_module_config(ctx, ib_core_module(),
                                  (void *)&corecfg);
    if (rc != IB_OK) {
        IB_FTRACE_RET_PTR(ib_provider_inst_t, NULL);
    }

    IB_FTRACE_RET_PTR(ib_provider_inst_t, corecfg->pi.logger);
}
Exemple #8
0
/**
 * 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;
}
Exemple #9
0
ib_status_t ib_parser_provider_set_instance(ib_context_t *ctx, ib_provider_inst_t *pi)
{
    IB_FTRACE_INIT();
    ib_core_cfg_t *corecfg;
    ib_status_t rc;

    rc = ib_context_module_config(ctx, ib_core_module(),
                                  (void *)&corecfg);
    if (rc != IB_OK) {
        IB_FTRACE_RET_STATUS(rc);
    }

    corecfg->pi.parser = pi;

    IB_FTRACE_RET_STATUS(rc);
}
Exemple #10
0
void ib_log_provider_set_instance(ib_context_t *ctx, ib_provider_inst_t *pi)
{
    IB_FTRACE_INIT();
    ib_core_cfg_t *corecfg;
    ib_status_t rc;

    rc = ib_context_module_config(ctx, ib_core_module(),
                                  (void *)&corecfg);
    if (rc != IB_OK) {
        /// @todo This func should return ib_status_t now
        IB_FTRACE_RET_VOID();
    }

    corecfg->pi.logger = pi;

    IB_FTRACE_RET_VOID();
}
Exemple #11
0
/**
 * @internal
 *
 * "Sniffs" the output (response) data from the connection stream.
 */
static int ironbee_output_filter (ap_filter_t *f, apr_bucket_brigade *bb)
{
    apr_bucket *b;
#if 0
    conn_rec *c = f->c;
    ironbee_conn_context *ctx = f->ctx;
    ib_conn_t *iconn = ctx->iconn;
    ib_core_cfg_t *corecfg;
    int buffering = 0;

    /* Configure. */
    ib_context_module_config(iconn->ctx, ib_core_module(), (void *)&corecfg);
    if (corecfg != NULL) {
        buffering = (int)corecfg->buffer_res;
    }
#endif


    for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) {
#if 0
        /// @todo Should this be done?  Maybe only for proxy?
        if (APR_BUCKET_IS_EOS(b)) {
            /// @todo Do we need to do this? Maybe only for proxy.
            apr_bucket *flush = apr_bucket_flush_create(f->c->bucket_alloc);
            APR_BUCKET_INSERT_BEFORE(b, flush);
        }

        if (buffering) {
            /// @todo setaside into our own pool to destroy later???
            apr_bucket_setaside(b, c->pool);
            process_bucket(f, b);
            APR_BUCKET_REMOVE(b);
        }
        else {
#endif
            process_bucket(f, b);
#if 0
        }
#endif
    }

    return ap_pass_brigade(f->next, bb);
}
Exemple #12
0
/**
 * 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);
}
Exemple #13
0
ib_status_t core_audit_open(ib_provider_inst_t *lpi,
                            ib_auditlog_t *log)
{
    IB_FTRACE_INIT();
    core_audit_cfg_t *cfg = (core_audit_cfg_t *)log->cfg_data;
    ib_core_cfg_t *corecfg;
    ib_status_t rc;

    /* Non const struct we will build and then assign to
     * corecfg->auditlog_index_hp. */
    ib_logformat_t *auditlog_index_hp;

    assert(NULL != lpi);
    assert(NULL != log);
    assert(NULL != log->ctx);
    assert(NULL != log->ctx->auditlog);

    rc = ib_context_module_config(log->ctx, ib_core_module(),
                                  (void *)&corecfg);
    if (rc != IB_OK) {
        ib_log_error(log->ib,  "Could not fetch core configuration: %s", ib_status_to_string(rc) );
        IB_FTRACE_RET_STATUS(rc);
    }

    assert(NULL != corecfg);

    /* Copy the FILE* into the core_audit_cfg_t. */
    if (log->ctx->auditlog->index_fp != NULL) {
        cfg->index_fp = log->ctx->auditlog->index_fp;
    }

    /* If we have a file name but no file pointer, assign cfg->index_fp. */
    else if ((log->ctx->auditlog->index != NULL) && (cfg->index_fp == NULL)) {

        /**
         * Open the audit log index file. If the file name starts with
         * a | a pipe is opened to a subprocess, etc...
         */
        rc = core_audit_open_auditindexfile(lpi, log, cfg, corecfg);

        if (rc != IB_OK) {
            ib_log_error(log->ib,  "Could not open auditlog index.");
            IB_FTRACE_RET_STATUS(rc);
        }
    }

    /* Open audit file that contains the record identified by the line
     * written in index_fp. */
    if (cfg->fp == NULL) {
        rc = core_audit_open_auditfile(lpi, log, cfg, corecfg);

        if (rc!=IB_OK) {
            ib_log_error(log->ib,  "Failed to open audit log file.");
            IB_FTRACE_RET_STATUS(rc);
        }
    }

    /* Set the Audit Log index format */
    if (corecfg->auditlog_index_hp == NULL) {
        rc = ib_logformat_create(log->ib->mp, &auditlog_index_hp);
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }
        if (corecfg->auditlog_index_fmt != NULL) {
            rc = ib_logformat_set(auditlog_index_hp,
                                  corecfg->auditlog_index_fmt);
        }
        else {
            rc = ib_logformat_set(auditlog_index_hp, IB_LOGFORMAT_DEFAULT);
        }
        if (rc != IB_OK) {
            IB_FTRACE_RET_STATUS(rc);
        }

        /* Commit built struct. */
        corecfg->auditlog_index_hp = auditlog_index_hp;
    }

    IB_FTRACE_RET_STATUS(IB_OK);
}
Exemple #14
0
/**
 * @internal
 *
 * "Sniffs" the input (request) data from the connection stream and tries
 * to determine who closed a connection and why.
 */
static int ironbee_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
                                ap_input_mode_t mode, apr_read_type_e block,
                                apr_off_t readbytes)
{
    conn_rec *c = f->c;
    ironbee_conn_context *ctx = f->ctx;
    ib_conn_t *iconn = ctx->iconn;
    ib_core_cfg_t *corecfg;
    ib_stream_t *istream;
    apr_bucket *b;
    apr_status_t rc;
    int buffering = 0;

    /* Any mode not handled just gets passed through. */
    if ((mode != AP_MODE_GETLINE) && (mode != AP_MODE_READBYTES)) {
        return ap_get_brigade(f->next, bb, mode, block, readbytes);
    }

    /* Configure. */
    ib_context_module_config(iconn->ctx, ib_core_module(), (void *)&corecfg);
    if (corecfg != NULL) {
        buffering = (int)corecfg->buffer_req;
    }

    /* When buffering, data is removed from the brigade and handed
     * to IronBee. The filter must not return an empty brigade in this
     * case and keeps reading until there is processed data that comes
     * back from IronBee.
     */
    do {
        ib_tx_t *itx = iconn->tx;

        /* If there is any processed data, then send it now. */
        if (buffering && (itx != NULL)) {
            ib_sdata_t *sdata;

            /* Take any data from the drain (processed data) and
             * inject it back into the filter brigade.
             */
            ib_fctl_drain(itx->fctl, &istream);
            if ((istream != NULL) && (istream->nelts > 0)) {
                int done = 0;

                while (!done) {
                    apr_bucket *ibucket = NULL;

                    /// @todo Handle multi-bucket lines
                    if (mode == AP_MODE_GETLINE) {
                        done = 1;
                    }

                    ib_stream_pull(istream, &sdata);
                    if (sdata == NULL) {
                        /* No more data left. */
                        break;
                    }

                    switch (sdata->type) {
                        case IB_STREAM_DATA:
#ifdef IB_DEBUG
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": DATA[%d]: %.*s", (int)sdata->dlen, (int)sdata->dlen, (char *)sdata->data);
#endif
                            
                            /// @todo Is this creating a copy?  Just need a reference.
                            ibucket = apr_bucket_heap_create(sdata->data,
                                                             sdata->dlen,
                                                             NULL,
                                                             bb->bucket_alloc);
                            break;
                        case IB_STREAM_FLUSH:
#ifdef IB_DEBUG
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": FLUSH");
#endif
                            ibucket = apr_bucket_flush_create(bb->bucket_alloc);
                            break;
                        case IB_STREAM_EOH:
#ifdef IB_DEBUG
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": EOH");
#endif
                            /// @todo Do something here???
                            break;
                        case IB_STREAM_EOB:
#ifdef IB_DEBUG
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": EOB");
#endif
                            /// @todo Do something here???
                            break;
                        case IB_STREAM_EOS:
#ifdef IB_DEBUG
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": EOS");
#endif
                            ibucket = apr_bucket_eos_create(bb->bucket_alloc);
                            break;
                        default:
                            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                                         IB_PRODUCT_NAME ": UNKNOWN stream data type %d", sdata->type);
                    }

                    if (ibucket != NULL) {
                        APR_BRIGADE_INSERT_TAIL(bb, ibucket);
                    }
                }

                /* Need to send any processed data to avoid deadlock. */
                if (!APR_BRIGADE_EMPTY(bb)) {
                    return APR_SUCCESS;
                }
            }
        }

        /* Fetch data from the next filter. */
        if (buffering) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                         "FETCH BRIGADE (buffering)");

            /* Normally Apache will request the headers line-by-line, but
             * IronBee does not require this.  So, here the request is
             * fetched with READBYTES and IronBee will then break
             * it back up into lines when it is injected back into
             * the brigade after the data is processed.
             */
            rc = ap_get_brigade(f->next,
                                bb,
                                AP_MODE_READBYTES,
                                block,
                                HUGE_STRING_LEN);
        }
        else {
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                         "FETCH BRIGADE (non-buffering)");
            rc = ap_get_brigade(f->next, bb, mode, block, readbytes);
        }

        /* Check for any timeouts/disconnects/errors. */
        if (APR_STATUS_IS_TIMEUP(rc)) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                         IB_PRODUCT_NAME ": %s server closed connection (%d)",
                         f->frec->name, rc);

            ap_remove_input_filter(f);
            return rc;
        }
        else if (APR_STATUS_IS_EOF(rc) || apr_get_os_error() == ECONNRESET) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                         IB_PRODUCT_NAME ": %s client closed connection (%d)",
                         f->frec->name, rc);

            ap_remove_input_filter(f);
            return rc;
        }
        else if (rc != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
                         IB_PRODUCT_NAME ": %s returned %d (0x%08x) - %s",
                         f->frec->name, rc, rc, strerror(apr_get_os_error()));

            return rc;
        }

        /* Process data. */
        for (b = APR_BRIGADE_FIRST(bb);
             b != APR_BRIGADE_SENTINEL(bb);
             b = APR_BUCKET_NEXT(b))
        {
            if (buffering) {
                /// @todo setaside into our own pool to destroy later???
                apr_bucket_setaside(b, c->pool);
                process_bucket(f, b);
                APR_BUCKET_REMOVE(b);
            }
            else {
                process_bucket(f, b);
            }
        }
    } while (buffering);

    return APR_SUCCESS;
}
Exemple #15
0
/**
 * 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;
}
Exemple #16
0
/**
 * 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;
}
Exemple #17
0
/**
 * 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;
}
Exemple #18
0
ib_status_t core_audit_close(ib_provider_inst_t *lpi, ib_auditlog_t *log)
{
    IB_FTRACE_INIT();
    core_audit_cfg_t *cfg = (core_audit_cfg_t *)log->cfg_data;
    ib_core_cfg_t *corecfg;
    ib_status_t ib_rc;
    int sys_rc;
    char line[IB_LOGFORMAT_MAXLINELEN + 2];
    int line_size = 0;

    /* Retrieve corecfg to get the AuditLogIndexFormat */
    ib_rc = ib_context_module_config(log->ctx, ib_core_module(),
                                     &corecfg);
    if (ib_rc != IB_OK) {
        ib_log_alert(log->ib,  "Failure accessing core module: %s", ib_status_to_string(ib_rc));
        IB_FTRACE_RET_STATUS(ib_rc);
    }

    /* Close the audit log. */
    if (cfg->fp != NULL) {
        fclose(cfg->fp);
        //rename temp to real
        sys_rc = rename(cfg->temp_path, cfg->full_path);
        if (sys_rc != 0) {
            sys_rc = errno;
            ib_log_error(log->ib,
                         "Error renaming auditlog %s: %s (%d)",
                         cfg->temp_path,
                         strerror(sys_rc), sys_rc);
            IB_FTRACE_RET_STATUS(IB_EOTHER);
        }
        ib_log_info(log->ib, "AUDITLOG: %s", cfg->full_path);
        cfg->fp = NULL;
    }

    /* Write to the index file if using one. */
    if ((cfg->index_fp != NULL) && (cfg->parts_written > 0)) {

        ib_lock_lock(&log->ctx->auditlog->index_fp_lock);

        ib_rc = core_audit_get_index_line(lpi, log, line, &line_size);

        if (ib_rc != IB_OK) {
            ib_lock_unlock(&log->ctx->auditlog->index_fp_lock);
            IB_FTRACE_RET_STATUS(ib_rc);
        }

        sys_rc = fwrite(line, line_size, 1, cfg->index_fp);

        if (sys_rc < 0) {
            sys_rc = errno;
            ib_log_error(log->ib,
                         "Could not write to audit log index: %s (%d)",
                         strerror(sys_rc), sys_rc);

            /// @todo Should retry (a piped logger may have died)
            fclose(cfg->index_fp);
            cfg->index_fp = NULL;

            log->ctx->auditlog->index_fp = cfg->index_fp;

            ib_lock_unlock(&log->ctx->auditlog->index_fp_lock);
            IB_FTRACE_RET_STATUS(IB_OK);
        }

        fflush(cfg->index_fp);
        ib_lock_unlock(&log->ctx->auditlog->index_fp_lock);
    }

    IB_FTRACE_RET_STATUS(IB_OK);
}
Exemple #19
0
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;
}
Exemple #20
0
/**
 * Handle request_header events for user agent extraction.
 *
 * Extract the "request_headers" field (a list) from the transactions's
 * data provider instance, then loop through the list, looking for the
 * "User-Agent"  field.  If found, the value is parsed and used to update the
 * connection object fields.
 *
 * @param[in] ib IronBee object
 * @param[in,out] tx Transaction.
 * @param[in] event Event type
 * @param[in] data Callback data (module)
 *
 * @returns Status code
 */
static ib_status_t modua_user_agent(ib_engine_t *ib,
                                    ib_tx_t *tx,
                                    ib_state_event_type_t event,
                                    void *data)
{
    assert(ib != NULL);
    assert(tx != NULL);
    assert(tx->var_store != NULL);
    assert(event == request_header_finished_event);
    assert(data != NULL);

    const ib_module_t *m = (const ib_module_t *)data;
    const ib_field_t  *req_agent = NULL;
    ib_status_t         rc = IB_OK;
    const ib_list_t *bs_list;
    const ib_bytestr_t *bs;
    const modua_config_t *cfg;

    rc = ib_context_module_config(ib_context_main(ib), m, &cfg);
    if (rc != IB_OK) {
        ib_log_error_tx(tx, "Can't fetch configuration: %s",
                        ib_status_to_string(rc));
        return rc;
    }

    /* Extract the User-Agent header field */
    rc = ib_var_target_get_const(
        cfg->user_agent,
        &bs_list,
        tx->mp,
        tx->var_store
    );
    if (rc == IB_ENOENT || ib_list_elements(bs_list) == 0) {
        ib_log_debug_tx(tx, "request_header_finished_event: No user agent");
        return IB_OK;
    }
    if (rc != IB_OK) {
        ib_log_error_tx(tx,
                        "Cannot retrieve request_headers:User-Agent: %d",
                        rc);
        return rc;
    }

    if (IB_LIST_ELEMENTS(bs_list) == 0) {
        ib_log_debug_tx(tx, "request_header_finished_event: No user agent");
        return IB_OK;
    }

    req_agent = (ib_field_t *)IB_LIST_NODE_DATA(IB_LIST_LAST(bs_list));

    /* Found it: copy the data into a newly allocated string buffer */
    rc = ib_field_value_type(req_agent,
                             ib_ftype_bytestr_out(&bs),
                             IB_FTYPE_BYTESTR);
    if (rc != IB_OK) {
        ib_log_error_tx(tx, "Request user agent is not a BYTESTR: %s",
                        ib_status_to_string(rc));
        return rc;
    }

    /* Finally, split it up & store the components */
    rc = modua_agent_fields(ib, tx, bs);
    return rc;
}
Exemple #21
0
/**
 * Handle request_header events for remote IP extraction.
 *
 * Extract the "request_headers" field (a list) from the transactions's
 * data provider instance, then loop through the list, looking for the
 * "X-Forwarded-For"  field.  If found, the first value in the (comma
 * separated) list replaces the local ip address string in the connection
 * object.
 *
 * @param[in] ib IronBee object
 * @param[in,out] tx Transaction object
 * @param[in] event Event type
 * @param[in] cbdata Callback data (module)
 *
 * @returns Status code
 */
static ib_status_t modua_remoteip(ib_engine_t *ib,
                                  ib_tx_t *tx,
                                  ib_state_event_type_t event,
                                  void *cbdata)
{
    assert(ib != NULL);
    assert(tx != NULL);
    assert(tx->var_store != NULL);
    assert(event == request_header_finished_event);

    const ib_module_t    *m = (const ib_module_t *)cbdata;
    ib_field_t           *field = NULL;
    ib_status_t           rc = IB_OK;
    const ib_bytestr_t   *bs;
    const uint8_t        *data;
    size_t                len;
    char                 *buf;
    uint8_t              *comma;
    const ib_list_t      *list;
    const ib_list_node_t *node;
    const ib_field_t     *forwarded;
    uint8_t              *stripped;
    size_t                num;
    ib_flags_t            flags;
    const modua_config_t *cfg;

    rc = ib_context_module_config(ib_context_main(ib), m, &cfg);
    if (rc != IB_OK) {
        ib_log_error_tx(tx, "Can't fetch configuration: %s",
                        ib_status_to_string(rc));
        return rc;
    }

    ib_log_debug3_tx(tx, "Checking for alternate remote address");

    /* Extract the X-Forwarded-For header field */
    rc = ib_var_target_get_const(
        cfg->forwarded_for,
        &list,
        tx->mp,
        tx->var_store
    );
    if (rc == IB_ENOENT || ib_list_elements(list) == 0) {
        ib_log_debug_tx(tx, "No X-Forwarded-For");
        return IB_OK;
    }
    if (rc != IB_OK) {
        ib_log_error_tx(tx,
                        "Cannot retrieve request_headers:User-Agent: %d",
                        rc);
        return rc;
    }

    num = ib_list_elements(list);
    if (num == 0) {
        ib_log_debug_tx(tx, "No X-Forwarded-For header found");
        return rc;
    }
    else if (num != 1) {
        ib_log_debug_tx(tx, "%zd X-Forwarded-For headers found: ignoring", num);
        return rc;
    }
    node = ib_list_last_const(list);
    if ( (node == NULL) || (node->data == NULL) ) {
        ib_log_notice_tx(tx, "Invalid X-Forwarded-For header found");
        return rc;
    }
    forwarded = (const ib_field_t *)node->data;

    /* Found it: copy the data into a newly allocated string buffer */
    rc = ib_field_value_type(forwarded,
                             ib_ftype_bytestr_out(&bs),
                             IB_FTYPE_BYTESTR);
    if (rc != IB_OK) {
        ib_log_notice_tx(tx, "Invalid X-Forwarded-For header value");
        return rc;
    }

    if (bs == NULL) {
        ib_log_notice_tx(tx, "X-Forwarded-For header not a bytestr");
        return IB_EINVAL;
    }
    len = ib_bytestr_length(bs);
    data = ib_bytestr_const_ptr(bs);

    /* Search for a comma in the buffer */
    comma = memchr(data, ',', len);
    if (comma != NULL) {
        len = comma - data;
    }

    /* Trim whitespace */
    stripped = (uint8_t *)data;
    rc = ib_strtrim_lr_ex(IB_STROP_INPLACE, tx->mp,
                          stripped, len,
                          &stripped, &len, &flags);
    if (rc != IB_OK) {
        return rc;
    }

    /* Verify that it looks like a valid IP v4/6 address */
    rc = ib_ip_validate_ex((const char *)stripped, len);
    if (rc != IB_OK) {
        ib_log_error_tx(tx,
            "X-Forwarded-For \"%.*s\" is not a valid IP address",
            (int)len, stripped
        );
        return IB_OK;
    }

    /* Allocate memory for copy of stripped string */
    buf = (char *)ib_mpool_alloc(tx->mp, len+1);
    if (buf == NULL) {
        ib_log_error_tx(tx,
                        "Failed to allocate %zd bytes for remote address",
                        len+1);
        return IB_EALLOC;
    }

    /* Copy the string out */
    memcpy(buf, stripped, len);
    buf[len] = '\0';

    ib_log_debug_tx(tx, "Remote address changed to \"%s\"", buf);

    /* This will lose the pointer to the original address
     * buffer, but it should be cleaned up with the rest
     * of the memory pool. */
    tx->er_ipstr = buf;

    /* Update the remote address field in the tx collection */
    rc = ib_field_create_bytestr_alias(
        &field,
        tx->mp,
        "", 0,
        (uint8_t *)buf, len
    );
    if (rc != IB_OK) {
        ib_log_error_tx(tx, "Failed to create field for remote_addr: %s",
                        ib_status_to_string(rc));
        return rc;
    }
    rc = ib_var_source_set(cfg->remote_addr, tx->var_store, field);
    if (rc != IB_OK) {
        ib_log_error_tx(tx,
                        "Failed to set remote address var: %s",
                        ib_status_to_string(rc));
        return rc;
    }

    return IB_OK;
}
Exemple #22
0
/**
 * 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);
}
Exemple #23
0
/**
 * Called at context close.  Initialized user-agent target.
 *
 * @param[in] ib Engine
 * @param[in] ctx Context
 * @param[in] event Event triggering the callback
 * @param[in] cbdata Callback data (module).
 *
 * @returns Status code
 */
static
ib_status_t modua_ctx_close(
    ib_engine_t           *ib,
    ib_context_t          *ctx,
    ib_state_event_type_t  event,
    void                  *cbdata
)
{
    ib_module_t *m = (ib_module_t *)cbdata;
    if (ib_context_type(ctx) == IB_CTYPE_MAIN) {
        modua_config_t *cfg;
        ib_var_target_t *target;
        ib_status_t rc;

        rc = ib_context_module_config(ctx, m, &cfg);
        if (rc != IB_OK) {
            ib_log_error(ib, "Can't fetch configuration: %s",
                         ib_status_to_string(rc));
            return rc;
        }

        rc = ib_var_target_acquire_from_string(
            &target,
            ib_engine_pool_main_get(ib),
            ib_engine_var_config_get(ib),
            IB_S2SL("request_headers:User-Agent"),
            NULL, NULL
        );
        if (rc != IB_OK) {
            ib_log_error(ib,
                         "Error acquiring target for User-Agent header: %s",
                         ib_status_to_string(rc));
            return rc;
        }
        cfg->user_agent = target;

        rc = ib_var_target_acquire_from_string(
            &target,
            ib_engine_pool_main_get(ib),
            ib_engine_var_config_get(ib),
            IB_S2SL("request_headers:X-Forwarded-For"),
            NULL, NULL
        );
        if (rc != IB_OK) {
            ib_log_error(ib,
                         "Error acquiring target for X-Forwarded-For header: %s",
                         ib_status_to_string(rc));
            return rc;
        }
        cfg->forwarded_for = target;

        rc = ib_var_source_acquire(
            &(cfg->remote_addr),
            ib_engine_pool_main_get(ib),
            ib_engine_var_config_get(ib),
            IB_S2SL("remote_addr")
        );
        if (rc != IB_OK) {
            ib_log_error(ib,
                         "Error acquiring source for remote_addr"
                          " header: %s",
                         ib_status_to_string(rc));
            return rc;
        }
    }

    return IB_OK;
}
Exemple #24
0
ib_status_t core_audit_get_index_line(ib_provider_inst_t *lpi,
                                      ib_auditlog_t *log,
                                      char *line,
                                      int *line_size)
{
    IB_FTRACE_INIT();
    core_audit_cfg_t *cfg = (core_audit_cfg_t *)log->cfg_data;
    ib_core_cfg_t *corecfg;
    ib_tx_t *tx = log->tx;
    ib_conn_t *conn = tx->conn;
    ib_site_t *site = ib_context_site_get(log->ctx);
    const ib_logformat_t *lf;
    ib_status_t rc;
    char *ptr = line;
    char *tstamp = NULL;
    uint8_t which;
    int i = 0;
    int l = 0;
    int used = 0;
    const char *aux = NULL;

    /* Retrieve corecfg to get the AuditLogIndexFormat */
    rc = ib_context_module_config(log->ctx, ib_core_module(),
                                  (void *)&corecfg);

    if (rc != IB_OK) {
        IB_FTRACE_RET_STATUS(rc);
    }

    lf = corecfg->auditlog_index_hp;
    which = lf->literal_starts ? 1 : 0;

    for (; (i < lf->field_cnt || l < lf->literal_cnt) &&
            used < IB_LOGFORMAT_MAXLINELEN;)
    {
        if (which++ % 2 == 0) {
            int aux_i = 0;

            switch (lf->fields[i]) {
                case IB_LOG_FIELD_REMOTE_ADDR:
                    aux = tx->er_ipstr;
                    break;
                case IB_LOG_FIELD_LOCAL_ADDR:
                    aux = conn->local_ipstr;
                    break;
                case IB_LOG_FIELD_HOSTNAME:
                     aux = tx->hostname;
                    break;
                case IB_LOG_FIELD_SITE_ID:
                    if (site == NULL) {
                         aux = (char *)"-";
                    }
                    else {
                         aux = site->id_str;
                    }
                    break;
                case IB_LOG_FIELD_SENSOR_ID:
                     aux = log->ib->sensor_id_str;
                    break;
                case IB_LOG_FIELD_TRANSACTION_ID:
                     aux = tx->id;
                    break;
                case IB_LOG_FIELD_TIMESTAMP:
                    /* Prepare timestamp (only if needed) */
                    tstamp = (char *)ib_mpool_alloc(log->mp, 30);
                    if (tstamp == NULL) {
                        IB_FTRACE_RET_STATUS(IB_EALLOC);
                    }

                    ib_clock_timestamp(tstamp, &tx->tv_created);
                    aux = tstamp;
                    break;
                case IB_LOG_FIELD_LOG_FILE:
                    aux = cfg->fn;
                    break;
                default:
                    ptr[used++] = '\n';
                    /* Not understood */
                    IB_FTRACE_RET_STATUS(IB_EINVAL);
                    break;
            }

            for (; aux != NULL && aux[aux_i] != '\0';) {
                if (used < IB_LOGFORMAT_MAXLINELEN) {
                    ptr[used++] = aux[aux_i++];
                }
                else {
                    ptr[used++] = '\n';
                    IB_FTRACE_RET_STATUS(IB_ETRUNC);
                }
            }
            ++i;
        }
        else {
            /* Use literals */
            if (used + lf->literals_len[l] < IB_LOGFORMAT_MAXLINELEN) {
                memcpy(&ptr[used], lf->literals[l], lf->literals_len[l]);
                used += lf->literals_len[l];
                ++l;
            }
            else {
                /* Truncated.. */
                ptr[used++] = '\n';
                IB_FTRACE_RET_STATUS(IB_ETRUNC);
            }
        }
    }
    ptr[used++] = '\n';
    *line_size = used;

    IB_FTRACE_RET_STATUS(IB_OK);
}
Exemple #25
0
/**
 * @internal
 * Handle a PocSig directive.
 *
 * @param cp Config parser
 * @param name Directive name
 * @param args List of directive arguments
 * @param cbdata Callback data (from directive registration)
 *
 * @returns Status code
 */
static ib_status_t pocsig_dir_signature(ib_cfgparser_t *cp,
                                        const char *name,
                                        ib_list_t *args,
                                        void *cbdata)
{
    IB_FTRACE_INIT(pocsig_dir_signature);
    ib_engine_t *ib = cp->ib;
    ib_context_t *ctx = cp->cur_ctx ? cp->cur_ctx : ib_context_main(ib);
    ib_list_t *list;
    const char *target;
    const char *op;
    const char *action;
    pocsig_cfg_t *cfg;
    pocsig_phase_t phase;
    pocsig_sig_t *sig;
    const char *errptr;
    int erroff;
    ib_status_t rc;

    /* Get the pocsig configuration for this context. */
    rc = ib_context_module_config(ctx, IB_MODULE_STRUCT_PTR, (void *)&cfg);
    if (rc != IB_OK) {
        ib_log_error(ib, 1, "Failed to fetch %s config: %d",
                     MODULE_NAME_STR, rc);
    }

    /* Setup the PCRE matcher. */
    if (cfg->pcre == NULL) {
        rc = ib_matcher_create(ib, ib_engine_pool_config_get(ib),
                               "pcre", &cfg->pcre);
        if (rc != IB_OK) {
            ib_log_error(ib, 2, "Could not create a PCRE matcher: %d", rc);
            IB_FTRACE_RET_STATUS(rc);
        }
    }

    /* Determine phase and initialize the phase list if required. */
    if (strcasecmp("PocSigPreTx", name) == 0) {
        phase = POCSIG_PRE;
        if (cfg->phase[phase] == NULL) {
            rc = ib_list_create(cfg->phase + POCSIG_PRE,
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
        }
    }
    else if (strcasecmp("PocSigReqHead", name) == 0) {
        phase = POCSIG_REQHEAD;
        if (cfg->phase[phase] == NULL) {
            ib_log_debug(ib, 4, "Creating list for phase=%d", phase);
            rc = ib_list_create(&list,
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
            ib_log_debug(ib, 4, "List for phase=%d list=%p", phase, list);
            cfg->phase[phase] = list;
        }
    }
    else if (strcasecmp("PocSigReq", name) == 0) {
        phase = POCSIG_REQ;
        if (cfg->phase[phase] == NULL) {
            rc = ib_list_create(&cfg->phase[phase],
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
        }
    }
    else if (strcasecmp("PocSigResHead", name) == 0) {
        phase = POCSIG_RESHEAD;
        if (cfg->phase[phase] == NULL) {
            rc = ib_list_create(&cfg->phase[phase],
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
        }
    }
    else if (strcasecmp("PocSigRes", name) == 0) {
        phase = POCSIG_RES;
        if (cfg->phase[POCSIG_RES] == NULL) {
            rc = ib_list_create(&cfg->phase[POCSIG_RES],
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
        }
    }
    else if (strcasecmp("PocSigPostTx", name) == 0) {
        phase = POCSIG_POST;
        if (cfg->phase[phase] == NULL) {
            rc = ib_list_create(&cfg->phase[phase],
                                ib_engine_pool_config_get(ib));
            if (rc != IB_OK) {
                IB_FTRACE_RET_STATUS(rc);
            }
        }
    }
    else {
        ib_log_error(ib, 2, "Invalid signature: %s", name);
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    /* Target */
    rc = ib_list_shift(args, &target);
    if (rc != IB_OK) {
        ib_log_error(ib, 1, "No PocSig target");
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    /* Operator */
    rc = ib_list_shift(args, &op);
    if (rc != IB_OK) {
        ib_log_error(ib, 1, "No PocSig operator");
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    /* Action */
    rc = ib_list_shift(args, &action);
    if (rc != IB_OK) {
        ib_log_debug(ib, 4, "No PocSig action");
        action = "";
    }

    /* Signature */
    sig = (pocsig_sig_t *)ib_mpool_alloc(ib_engine_pool_config_get(ib),
                                         sizeof(*sig));
    if (sig == NULL) {
        IB_FTRACE_RET_STATUS(IB_EALLOC);
    }

    sig->target = ib_mpool_strdup(ib_engine_pool_config_get(ib), target);
    sig->patt = ib_mpool_strdup(ib_engine_pool_config_get(ib), op);
    sig->emsg = ib_mpool_strdup(ib_engine_pool_config_get(ib), action);

    /* Compile the PCRE patt. */
    if (cfg->pcre == NULL) {
        ib_log_error(ib, 2, "No PCRE matcher available (load the pcre module?)");
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }
    sig->cpatt = ib_matcher_compile(cfg->pcre, sig->patt, &errptr, &erroff);
    if (sig->cpatt == NULL) {
        ib_log_error(ib, 2, "Error at offset=%d of PCRE patt=\"%s\": %s",
                     erroff, sig->patt, errptr);
        IB_FTRACE_RET_STATUS(IB_EINVAL);
    }

    ib_log_debug(ib, 4, "POCSIG: \"%s\" \"%s\" \"%s\" phase=%d ctx=%p",
                 target, op, action, phase, ctx);

    /* Add the signature to the phase list. */
    rc = ib_list_push(cfg->phase[phase], sig);
    if (rc != IB_OK) {
        ib_log_error(ib, 1, "Failed to add signature");
        IB_FTRACE_RET_STATUS(rc);
    }

    IB_FTRACE_RET_STATUS(IB_OK);
}
Exemple #26
0
/**
 * @internal
 * Handle signature execution.
 *
 * @param ib Engine
 * @param tx Transaction
 * @param cbdata Phase passed as pointer value
 *
 * @return Status code
 */
static ib_status_t pocsig_handle_sigs(ib_engine_t *ib,
                                      ib_tx_t *tx,
                                      void *cbdata)
{
    IB_FTRACE_INIT(pocsig_handle_post);
    pocsig_cfg_t *cfg;
    pocsig_phase_t phase = (pocsig_phase_t)(uintptr_t)cbdata;
    ib_list_t *sigs;
    ib_list_node_t *node;
    int dbglvl;
    ib_status_t rc;

    /* Get the pocsig configuration for this context. */
    rc = ib_context_module_config(tx->ctx, IB_MODULE_STRUCT_PTR, (void *)&cfg);
    if (rc != IB_OK) {
        ib_log_error(ib, 1, "Failed to fetch %s config: %d",
                     MODULE_NAME_STR, rc);
    }

    /* If tracing is enabled, lower the log level. */
    dbglvl = cfg->trace ? 4 : 9;

    /* Get the list of sigs for this phase. */
    sigs = cfg->phase[phase];
    if (sigs == NULL) {
        ib_log_debug(ib, dbglvl, "No signatures for phase=%d ctx=%p",
                     phase, tx->ctx);
        IB_FTRACE_RET_STATUS(IB_OK);
    }

    ib_log_debug(ib, dbglvl, "Executing %d signatures for phase=%d ctx=%p",
                 ib_list_elements(sigs), phase, tx->ctx);

    /* Run all the sigs for this phase. */
    IB_LIST_LOOP(sigs, node) {
        pocsig_sig_t *s = (pocsig_sig_t *)ib_list_node_data(node);
        ib_field_t *f;

        /* Fetch the field. */
        rc = ib_data_get(tx->dpi, s->target, &f);
        if (rc != IB_OK) {
            ib_log_error(ib, 4, "PocSig: No field named \"%s\"", s->target);
            continue;
        }

        /* Perform the match. */
        ib_log_debug(ib, dbglvl, "PocSig: Matching \"%s\" against field \"%s\"",
                     s->patt, s->target);
        rc = ib_matcher_match_field(cfg->pcre, s->cpatt, 0, f, NULL);
        if (rc == IB_OK) {
            ib_logevent_t *e;

            ib_log_debug(ib, dbglvl, "PocSig MATCH: %s at %s", s->patt, s->target);

            /* Create the event. */
            rc = ib_logevent_create(
                &e,
                tx->mp,
                "-",
                IB_LEVENT_TYPE_ALERT,
                IB_LEVENT_ACT_UNKNOWN,
                IB_LEVENT_PCLASS_UNKNOWN,
                IB_LEVENT_SCLASS_UNKNOWN,
                90,
                80,
                IB_LEVENT_SYS_UNKNOWN,
                IB_LEVENT_ACTION_IGNORE,
                IB_LEVENT_ACTION_IGNORE,
                s->emsg
            );
            if (rc != IB_OK) {
                ib_log_error(ib, 3, "PocSig: Error generating event: %d", rc);
                continue;
            }

            /* Log the event. */
            ib_clog_event(tx->ctx, e);
        }
        else {
            ib_log_debug(ib, dbglvl, "PocSig NOMATCH");
        }
    }