/** * IronBee callback function to set an HTTP error status. * This will divert processing into an ErrorDocument for the status. * * @param[in] tx - IronBee transaction * @param[in] status - Status to set * @return OK, or Declined if called too late. NOTIMPL should never happen. */ static ib_status_t ib_error_callback(ib_tx_t *tx, int status, void *cbdata) { ngxib_req_ctx *ctx = tx->sctx; if (status >= 200 && status < 600) { if (ctx->status >= 200 && ctx->status < 600) { ib_log_notice_tx(tx, "Ignoring: status already set to %d", ctx->status); return IB_OK; } if (ctx->start_response) { ib_log_notice_tx(tx, "Too late to change status=%d", status); return IB_DECLINED; } ib_log_info_tx(tx, "Setting status: %d -> %d", ctx->status, status); ctx->status = status; return IB_OK; } return IB_ENOTIMPL; }
/** * A Null identity check for the null (unconfigured) identity provider * * @param tx The tx * @return NULL */ static const char *dummy_id(ib_tx_t *tx) { ib_log_info_tx(tx, "Dummy ident check doing nothing"); return NULL; }
/** * 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 (not used) * * @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) { IB_FTRACE_INIT(); assert(ib != NULL); assert(tx != NULL); assert(tx->dpi != NULL); assert(event == request_header_finished_event); 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; ib_log_debug3_tx(tx, "Checking for alternate remote address"); /* Extract the X-Forwarded-For from the provider instance */ rc = ib_data_get(tx->dpi, "request_headers:X-Forwarded-For", &field); if ( (field == NULL) || (rc != IB_OK) ) { ib_log_debug_tx(tx, "No X-Forwarded-For field"); IB_FTRACE_RET_STATUS(IB_OK); } /* Because we asked for a filtered item, what we get back is a list */ rc = ib_field_value(field, ib_ftype_list_out(&list)); if (rc != IB_OK) { ib_log_debug_tx(tx, "No request header collection"); IB_FTRACE_RET_STATUS(rc); } num = ib_list_elements(list); if (num == 0) { ib_log_debug_tx(tx, "No X-Forwarded-For header found"); IB_FTRACE_RET_STATUS(rc); } else if (num != 1) { ib_log_debug_tx(tx, "%zd X-Forwarded-For headers found: ignoring", num); IB_FTRACE_RET_STATUS(rc); } node = ib_list_last_const(list); if ( (node == NULL) || (node->data == NULL) ) { ib_log_notice_tx(tx, "Invalid X-Forwarded-For header found"); IB_FTRACE_RET_STATUS(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"); IB_FTRACE_RET_STATUS(rc); } if (bs == NULL) { ib_log_notice_tx(tx, "X-Forwarded-For header not a bytestr"); IB_FTRACE_RET_STATUS(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) { IB_FTRACE_RET_STATUS(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 ); IB_FTRACE_RET_STATUS(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); IB_FTRACE_RET_STATUS(IB_EALLOC); } /* Copy the string out */ memcpy(buf, stripped, len); buf[len] = '\0'; ib_log_info_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_data_add_bytestr(tx->dpi, "remote_addr", (uint8_t*)buf, len, NULL); if (rc != IB_OK) { ib_log_error_tx(tx, "Failed to create remote address TX field: %s", ib_status_to_string(rc)); IB_FTRACE_RET_STATUS(rc); } IB_FTRACE_RET_STATUS(IB_OK); }