예제 #1
0
//#define mechanics_debug
static ngx_int_t ngx_http_dummy_access_handler(ngx_http_request_t *r)
{
  ngx_http_request_ctx_t	*ctx;
  ngx_int_t			rc;
  ngx_http_dummy_loc_conf_t	*cf;
  ngx_http_core_loc_conf_t  *clcf;
  struct tms		 tmsstart, tmsend;
  clock_t		 start, end;
  
  ctx = ngx_http_get_module_ctx(r, ngx_http_naxsi_module);
  cf = ngx_http_get_module_loc_conf(r, ngx_http_naxsi_module);

  clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
  /* ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, */
  /* 		"naxsi_entry_point"); */
  
  if (ctx && ctx->over)
    return (NGX_DECLINED);
  if (ctx && ctx->wait_for_body) {
#ifdef mechanics_debug
    ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "naxsi:NGX_AGAIN");
#endif
    return (NGX_DONE);
  }
  if (!cf) 
    return (NGX_ERROR);
  /* the module is not enabled here */
  if (!cf->enabled || cf->force_disabled)
    return (NGX_DECLINED);
  /* don't process internal requests. */
  if (r->internal) {
#ifdef mechanics_debug
    ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-DON'T PROCESS (%V)|CTX:%p|ARGS:%V|METHOD=%s|INTERNAL:%d", &(r->uri), ctx, &(r->args),
		  r->method == NGX_HTTP_POST ? "POST" : r->method == NGX_HTTP_PUT ? "PUT" : r->method == NGX_HTTP_GET ? "GET" : "UNKNOWN!!",
		  r->internal);
#endif
    return (NGX_DECLINED);
  }
#ifdef mechanics_debug
  ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  		"XX-processing (%V)|CTX:%p|ARGS:%V|METHOD=%s|INTERNAL:%d", &(r->uri), ctx, &(r->args),
		r->method == NGX_HTTP_POST ? "POST" : r->method == NGX_HTTP_PUT ? "PUT" : r->method == NGX_HTTP_GET ? "GET" : "UNKNOWN!!",
		r->internal);
#endif
  if (!ctx) {
    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_request_ctx_t));
    /* might have been set by a previous trigger */
    if (cf->learning)	{
      clcf->post_action.data = 0; //cf->denied_url->data;
      clcf->post_action.len = 0; //cf->denied_url->len;
    }
      
    if (ctx == NULL)
      return NGX_ERROR;
    ngx_http_set_ctx(r, ctx, ngx_http_naxsi_module);
    if  ((r->method == NGX_HTTP_POST || r->method == NGX_HTTP_PUT) 
	 && !ctx->ready) {
#ifdef mechanics_debug
      ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		    "XX-dummy : body_request : before !");
#endif
      rc = ngx_http_read_client_request_body(r, ngx_http_dummy_payload_handler);
      /* this might happen quite often, especially with big files / 
      ** low network speed. our handler is called when headers are read, 
      ** but, often, the full body request hasn't yet, so 
      ** read client request body will return ngx_again. Then we need
      ** to return ngx_done, wait for our handler to be called once 
      ** body request arrived, and let him call core_run_phases
      ** to be able to process the request.
      */
      if (rc == NGX_AGAIN) {
	ctx->wait_for_body = 1;
#ifdef mechanics_debug
	ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		      "XX-dummy : body_request : NGX_AGAIN !");
#endif
	return (NGX_DONE);
      }
      else
	if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
	  /* this debug print should be commented, but the thing is that
	  ** according to what I read into nginx src code, it may happen
	  ** and I haven't been abble to trigger this, so I just let it 
	  ** here to know when this special case will be triggered
	  */
	  ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
			"XX-dummy : SPECIAL RESPONSE !!!!");
	  return rc;
	}
    }
    else
      ctx->ready = 1;
  }
  if (ctx && ctx->ready && !ctx->over) {
    if ((start = times(&tmsstart)) == -1)
      ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		    "XX-dummy : Failed to get time");
    ngx_http_dummy_data_parse(ctx, r);
    cf->request_processed++;
    if ((end = times(&tmsend)) == -1)
      ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		    "XX-dummy : Failed to get time");
    if (end - start > 0)
      ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 
		    "[MORE THAN 1MS] times : start:%l end:%l diff:%l",
		    start, end, (end-start));
    ctx->over = 1;
    if (ctx->block) {
      cf->request_blocked++;
      rc = ngx_http_output_forbidden_page(ctx, r);
      //nothing:      return (NGX_OK);
      //redirect : return (NGX_HTTP_OK);
      return (rc);
    }
  }
#ifdef mechanics_debug
  ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		"NGX_FINISHED !");
#endif

  return (NGX_DECLINED);
}
예제 #2
0
/*
** [ENTRY POINT] does : this is the function called by nginx : 
** - Set up the context for the request
** - Check if the job is done and we're called again
** - if it's a POST/PUT request, setup hook for body dataz
** - call dummy_data_parse
** - check our context struct (with scores & stuff) against custom check rules
** - check if the request should be denied
*/
static ngx_int_t ngx_http_dummy_access_handler(ngx_http_request_t *r)
{
  ngx_http_request_ctx_t	*ctx;
  ngx_int_t			rc;
  ngx_http_dummy_loc_conf_t	*cf;
  struct tms		 tmsstart, tmsend;
  clock_t		 start, end;
  ngx_http_variable_value_t *lookup;


  static ngx_str_t learning_flag = ngx_string(RT_LEARNING);
  static ngx_str_t enable_flag = ngx_string(RT_ENABLE);
  static ngx_str_t post_action_flag = ngx_string(RT_POST_ACTION);
  static ngx_str_t extensive_log_flag = ngx_string(RT_EXTENSIVE_LOG);
  static ngx_str_t libinjection_sql_flag = ngx_string(RT_LIBINJECTION_SQL);
  static ngx_str_t libinjection_xss_flag = ngx_string(RT_LIBINJECTION_XSS);

  
  ctx = ngx_http_get_module_ctx(r, ngx_http_naxsi_module);
  cf = ngx_http_get_module_loc_conf(r, ngx_http_naxsi_module);
  
  if (ctx && ctx->over)
    return (NGX_DECLINED);
  if (ctx && ctx->wait_for_body) {   
    NX_DEBUG(_debug_mechanics, NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
	     "naxsi:NGX_AGAIN");
    return (NGX_DONE);
  }
  if (!cf) 
    return (NGX_ERROR);
  /* the module is not enabled here */
  /* if enable directive is not present at all in the location, 
     don't try to do dynamic lookup for "live" enabled
     naxsi, this would be very rude. */
  if (!cf->enabled)
    return (NGX_DECLINED);
  /* On the other hand, if naxsi has been explicitly disabled 
     in this location (using naxsi directive), user is probably
     trying to do something.  */
  if (cf->force_disabled) {
    /* Look if the user did not try to enable naxsi dynamically */
    lookup = ngx_http_get_variable(r, &enable_flag, cf->flag_enable_h);
    if (lookup && !lookup->not_found && lookup->len > 0) {
      ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		    "live enable is present %d", lookup->data[0] - '0');
      if (lookup->data[0] - '0' != 1) {
	return (NGX_DECLINED);}
    }
    else
      return (NGX_DECLINED);
  }
  /* don't process internal requests. */
  if (r->internal) {   
    NX_DEBUG(_debug_mechanics, NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
	     "XX-DON'T PROCESS (%V)|CTX:%p|ARGS:%V|METHOD=%s|INTERNAL:%d", &(r->uri), ctx, &(r->args),
	     r->method == NGX_HTTP_POST ? "POST" : r->method == NGX_HTTP_PUT ? "PUT" : r->method == NGX_HTTP_GET ? "GET" : "UNKNOWN!!",
	     r->internal);
    return (NGX_DECLINED);
  } 
  NX_DEBUG(_debug_mechanics, NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
	   "XX-processing (%V)|CTX:%p|ARGS:%V|METHOD=%s|INTERNAL:%d", &(r->uri), ctx, &(r->args),
	   r->method == NGX_HTTP_POST ? "POST" : r->method == NGX_HTTP_PUT ? "PUT" : r->method == NGX_HTTP_GET ? "GET" : "UNKNOWN!!",
	   r->internal);
  if (!ctx) {
    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_request_ctx_t));
    if (ctx == NULL)
      return NGX_ERROR;
    ngx_http_set_ctx(r, ctx, ngx_http_naxsi_module);
    NX_DEBUG(_debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
	     "XX-dummy : orig learning : %d", cf->learning ? 1 : 0);
    /* it seems that nginx will - in some cases - 
     have a variable with empty content but with lookup->not_found set to 0,
    so check len as well */
    ctx->learning = cf->learning;
    
    lookup = ngx_http_get_variable(r, &learning_flag, cf->flag_learning_h);
    if (lookup && !lookup->not_found && lookup->len > 0) {
      
      ctx->learning = lookup->data[0] - '0';     
      NX_DEBUG(_debug_modifier, NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
	       "XX-dummy : override learning : %d (raw=%d)", 
	       ctx->learning ? 1 : 0, lookup->len);
    }

    NX_DEBUG( _debug_modifier, 
    NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-dummy : [final] learning : %d", ctx->learning ? 1 : 0);


    ctx->enabled = cf->enabled;
    NX_DEBUG( _debug_modifier, 
    NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-dummy : orig enabled : %d", ctx->enabled ? 1 : 0);

    lookup = ngx_http_get_variable(r, &enable_flag, cf->flag_enable_h);
    if (lookup && !lookup->not_found && lookup->len > 0) {
      ctx->enabled = lookup->data[0] - '0';
      NX_DEBUG( _debug_modifier, 
      NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		    "XX-dummy : override enable : %d", ctx->enabled ? 1 : 0);


    }
    NX_DEBUG( _debug_modifier, 
    NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-dummy : [final] enabled : %d", ctx->enabled ? 1 : 0);



    /*
    ** LIBINJECTION_SQL
    */
    ctx->libinjection_sql = cf->libinjection_sql_enabled;

    NX_DEBUG( _debug_modifier, 
    NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-dummy : orig libinjection_sql : %d", ctx->libinjection_sql ? 1 : 0);


    lookup = ngx_http_get_variable(r, &libinjection_sql_flag, cf->flag_libinjection_sql_h);

    if (lookup && !lookup->not_found && lookup->len > 0) {
      ctx->libinjection_sql = lookup->data[0] - '0';
      NX_DEBUG( _debug_modifier, 
      NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		    "XX-dummy : override libinjection_sql : %d", ctx->libinjection_sql ? 1 : 0);

    }
    NX_DEBUG( _debug_modifier, 
    NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-dummy : [final] libinjection_sql : %d", ctx->libinjection_sql ? 1 : 0);

    /*
    ** LIBINJECTION_XSS
    */
    ctx->libinjection_xss = cf->libinjection_xss_enabled;

    NX_DEBUG( _debug_modifier, 
    NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-dummy : orig libinjection_xss : %d", ctx->libinjection_xss ? 1 : 0);


    lookup = ngx_http_get_variable(r, &libinjection_xss_flag, cf->flag_libinjection_xss_h);
    if (lookup && !lookup->not_found && lookup->len > 0) {
      ctx->libinjection_xss = lookup->data[0] - '0';
      NX_DEBUG( _debug_modifier, 
      NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		    "XX-dummy : override libinjection_xss : %d", ctx->libinjection_xss ? 1 : 0);

    }
    NX_DEBUG( _debug_modifier, 
    NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-dummy : [final] libinjection_xss : %d", ctx->libinjection_xss ? 1 : 0);


    /* post_action is off by default. */
    ctx->post_action = 0;
    NX_DEBUG( _debug_modifier    , 
    NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-dummy : orig post_action : %d", ctx->post_action ? 1 : 0);

    lookup = ngx_http_get_variable(r, &post_action_flag, cf->flag_post_action_h);
    if (lookup && !lookup->not_found && lookup->len > 0) {
      ctx->post_action = lookup->data[0] - '0';
      NX_DEBUG( _debug_modifier, 
      NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		    "XX-dummy : override post_action : %d", ctx->post_action ? 1 : 0);

    }
    NX_DEBUG( _debug_modifier, 
    NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-dummy : [final] post_action : %d", ctx->post_action ? 1 : 0);

    NX_DEBUG( _debug_modifier    , 
    NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-dummy : orig extensive_log : %d", ctx->extensive_log ? 1 : 0);

    lookup = ngx_http_get_variable(r, &extensive_log_flag, cf->flag_extensive_log_h);
    if (lookup && !lookup->not_found && lookup->len > 0) {
      ctx->extensive_log = lookup->data[0] - '0';
      NX_DEBUG( _debug_modifier, 
      NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		    "XX-dummy : override extensive_log : %d", ctx->extensive_log ? 1 : 0);

    }
    NX_DEBUG( _debug_modifier, 
    NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		  "XX-dummy : [final] extensive_log : %d", ctx->extensive_log ? 1 : 0);


    /* the module is not enabled here */
    if (!ctx->enabled)
      return (NGX_DECLINED);
    

    if  ((r->method == NGX_HTTP_POST || r->method == NGX_HTTP_PUT) 
	 && !ctx->ready) {
      NX_DEBUG( _debug_mechanics, NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		"XX-dummy : body_request : before !");
      
      rc = ngx_http_read_client_request_body(r, ngx_http_dummy_payload_handler);
      /* this might happen quite often, especially with big files / 
      ** low network speed. our handler is called when headers are read, 
      ** but, often, the full body request hasn't yet, so 
      ** read client request body will return ngx_again. Then we need
      ** to return ngx_done, wait for our handler to be called once 
      ** body request arrived, and let him call core_run_phases
      ** to be able to process the request.
      */
      if (rc == NGX_AGAIN) {
	ctx->wait_for_body = 1;
	NX_DEBUG( _debug_mechanics, 
	NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		      "XX-dummy : body_request : NGX_AGAIN !");

	return (NGX_DONE);
      }
      else
	if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
	  /* 
	  ** might happen but never saw it, let the debug print.
	  */
	  ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
			"XX-dummy : SPECIAL RESPONSE !!!!");
	  return rc;
	}
    }
    else
      ctx->ready = 1;
  }
  if (ctx && ctx->ready && !ctx->over) {
    
    if ((start = times(&tmsstart)) == (clock_t)-1)
      ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		    "XX-dummy : Failed to get time");
    ngx_http_dummy_data_parse(ctx, r);
    cf->request_processed++;
    if ((end = times(&tmsend)) == (clock_t)-1)
      ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
		    "XX-dummy : Failed to get time");
    if (end - start > 10)
      ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 
		    "[MORE THAN 10MS] times : start:%l end:%l diff:%l",
		    start, end, (end-start));
    ctx->over = 1;
    if (ctx->block || ctx->drop) {
      cf->request_blocked++;
      rc = ngx_http_output_forbidden_page(ctx, r);
      //nothing:      return (NGX_OK);
      //redirect : return (NGX_HTTP_OK);
      return rc;
    }
  }
  NX_DEBUG(_debug_mechanics, 
	   NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
	   "NGX_FINISHED !");

  return NGX_DECLINED;
}