Ejemplo n.º 1
0
static xmlCharEncoding sniff_encoding(saxctxt* ctx, const char* cbuf, size_t bytes)
{
  request_rec* r = ctx->f->r;
  cdn_conf* cfg = ctx->cfg;
  xmlCharEncoding ret;
  char* p;
  ap_regmatch_t match[2];
  char* buf = (char*)cbuf;
  const char *encoding = 0;

  /* If we've got it in the HTTP headers, there's nothing to do */
  if(r->content_type && (p = ap_strcasestr(r->content_type, "charset=")) && p != NULL) {
    p += 8;
    if((encoding = apr_pstrndup(r->pool, p, strcspn(p, " ;")))) {
      ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
                   "sniff_encoding: found charset %s in Content-Type", encoding);
      ret = xmlParseCharEncoding(encoding);
      if(((ret != XML_CHAR_ENCODING_ERROR) && (ret != XML_CHAR_ENCODING_NONE)))
        return ret;
    }
  }

  /* to sniff, first we look for BOM */
  if(encoding == NULL) {

    if((ret = xmlDetectCharEncoding((const xmlChar*)buf, bytes)) != XML_CHAR_ENCODING_NONE) {
      ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
                   "sniff_encoding: got charset from XML rules");
      return ret;
    }

    /* If none of the above, look for a META-thingey */
    if(ap_regexec(seek_meta_ctype, buf, 1, match, 0) == 0) {
      p = apr_pstrndup(r->pool, buf + match[0].rm_so, match[0].rm_eo - match[0].rm_so);
      if(ap_regexec(seek_charset, p, 2, match, 0) == 0)
        encoding = apr_pstrndup(r->pool, p+match[1].rm_so, match[1].rm_eo - match[1].rm_so);
    }

  }

  /* either it's set to something we found or it's still the default */
  if(encoding) {
    ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
                 "sniff_encoding: got charset %s from HTML META", encoding);
    ret = xmlParseCharEncoding(encoding);
    if(ret != XML_CHAR_ENCODING_ERROR && ret != XML_CHAR_ENCODING_NONE)
      return ret;

    ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
                 "sniff_encoding: charset %s not supported", encoding);
  }

  /* Use configuration default as a last resort */
  ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
               "sniff_encoding: no suitable charset information");
  return (cfg->default_encoding == XML_CHAR_ENCODING_NONE)
    ? XML_CHAR_ENCODING_8859_1 : cfg->default_encoding ;
}
Ejemplo n.º 2
0
/*
 * match version against a regular expression
 */
static int match_version(apr_pool_t *pool, char *version_string,
                         const char **error)
{
    regex_t *compiled;
    const char *to_match;
    int rc;

    compiled = ap_pregcomp(pool, version_string, REG_EXTENDED);
    if (!compiled) {
        *error = "Unable to compile regular expression";
        return 0;
    }

    *error = NULL;

    to_match = apr_psprintf(pool, "%d.%d.%d%s",
                            httpd_version.major,
                            httpd_version.minor,
                            httpd_version.patch,
                            httpd_version.add_string);

    rc = !ap_regexec(compiled, to_match, 0, NULL, 0);

    ap_pregfree(pool, compiled);
    return rc;    
}
Ejemplo n.º 3
0
static int cdn_request_handler(request_rec *r)
{
  cdn_conf *cfg = ap_get_module_config(r->per_dir_config, &cdn_module);

  /*
   * first, do originification, which only touches output headers, if
   * the object's request URL matches one of the CDNActAsOrigin
   * regexes
   */
  if(cfg->originify) {
    int i, verify_auth;
    act_as_origin_t *orig = (act_as_origin_t *)cfg->originify->elts;
    for(i = 0; i < cfg->originify->nelts; ++i) {
      if(!ap_regexec(&(orig[i].regex), r->uri, 0, 0, 0)) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
                     "cdn_request_handler: adding CDN origin headers for %s",
                     r->uri);
        verify_auth = add_origin_headers(cfg, r, &orig[i]);
        if(verify_auth && verify_auth_token(cfg, r) != OK)
          return HTTP_UNAUTHORIZED;
        break;
      }
    }
  }

  /* decide whether to install cdn_html_filter */
  if(cfg->content_types && cfg->links && cfg->map) {
    ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
                 "cdn_request_handler: adding cdn_html_filter for %s",
                 r->uri);
    ap_add_output_filter_handle(cdn_html_filter_handle, NULL, r, r->connection);
  }

  return DECLINED;
}
/**
 * Return the list of encoding(s) (defaults to (list "UTF-8"))
 * which named client is expected to send.
 *
 * @param r      Apache request object structure
 * @param encmap Table of UA-to-encoding(s)
 * @param lookup Name of the useragent to look for
 */
static array_header *
get_client_encoding(request_rec *r,
		    array_header *encmap, const char *lookup) {
  void         **list = (void **)encmap->elts;
  array_header  *encs = ap_make_array(r->pool, 1, sizeof(char *));

  int i;

  LOG(APLOG_DEBUG, r->server, "get_client_encoding: entered");

  /* push UTF-8 as the first candidate of expected encoding */
  *((char **)ap_push_array(encs)) = ap_pstrdup(r->pool, "UTF-8");

  if (! lookup)
    return encs;

  LOG(APLOG_DEBUG, r->server, "get_client_encoding: lookup == %s", lookup);

  for (i = 0 ; i < encmap->nelts ; i += 2) {
    if (ap_regexec((regex_t *)list[i], lookup, 0, NULL, 0) == 0) {
      LOG(APLOG_DEBUG, r->server, "get_client_encoding: entry found");
      ap_array_cat(encs, (array_header *)list[i + 1]);
      return encs;
    }
  }

  LOG(APLOG_DEBUG, r->server, "get_client_encoding: entry not found");
  return encs;
}
Ejemplo n.º 5
0
/**
 * The device is specified from UserAgent. 
 * @param r Request_rec is appointed.
 * @param userAgent UserAgent is appointed here,
 * @return The style which corresponds is returned.
 */
static device_table *
s_specified_device_from_xml(request_rec *r, mod_chxj_config * conf, const char *user_agent) 
{
  ap_regmatch_t        match[10];
  device_table         *returnType = &UNKNOWN_DEVICE;
  device_table_list    *dtl;
  device_table         *dt;
  char                 *device_id;

  DBG(r, "REQ[%X] start %s()", TO_ADDR(r),__func__);
  if (! user_agent) {
    DBG(r, "REQ[%X] end %s() (user_agent is not set)", TO_ADDR(r),__func__);
    return returnType;
  }
            


  if (! conf->devices) {
    ERR(r, "REQ[%X] device_data.xml load failure", TO_ADDR(r));
    DBG(r, "REQ[%X] end %s()", TO_ADDR(r), __func__);
    return returnType;
  }

  for (dtl = conf->devices; dtl; dtl = dtl->next) {
    if (! dtl->pattern) {
      continue;
    }

    /* DBG(r, "pattern is [%s]", dtl->pattern); */
    if (! dtl->regexp) {
      ERR(r,"REQ[%X] compile failed.", TO_ADDR(r));
      DBG(r, "REQ[%X] %s()", TO_ADDR(r),__func__);
      return returnType;
    }

    if (ap_regexec((const ap_regex_t *)dtl->regexp, user_agent, (apr_size_t)dtl->regexp->re_nsub + 1, match, 0) == 0) {
      device_id = ap_pregsub(r->pool, "$1", user_agent, dtl->regexp->re_nsub + 1, match);
      DBG(r, "REQ[%X] device_id:[%s]", TO_ADDR(r), device_id);

      dt = s_get_device_data(r, device_id, dtl);
      if (! dt) {
        dt = dtl->tail;
        if (dt){
          if (conf->detect_device_type > CHXJ_ADD_DETECT_DEVICE_TYPE_NONE ){
            dt->device_id = device_id;
          }
          DBG(r,"REQ[%X] end %s() (Not Found) use [%s]", TO_ADDR(r), __func__, dt->device_id);
          return dt;
        }
      }
      DBG(r,"REQ[%X] end %s() (Found) use [%s]", TO_ADDR(r), __func__, dt->device_id);
      return dt;
    }
  }

  DBG(r,"REQ[%X] end %s()", TO_ADDR(r), __func__);

  return returnType;
}
static int find_cookie(request_rec *r,char **user,uint8_t *secret,int secretLen) {
	char *cookie=0l;
	char *cookie_expire=0l;
	char *cookie_valid=0l;
	ap_regmatch_t regmatch[AP_MAX_REG_MATCH];
	authn_google_config_rec *conf = ap_get_module_config(r->per_dir_config, &authn_google_module);
	cookie = (char *) apr_table_get(r->headers_in, "Cookie");
	if (cookie) {
	if (conf->debugLevel) 
					ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
												"Found cookie \"%s\"",cookie);
		if (!ap_regexec(cookie_regexp, cookie, AP_MAX_REG_MATCH, regmatch, 0)) {
			if (user) *user  = ap_pregsub(r->pool, "$2", cookie,AP_MAX_REG_MATCH,regmatch);
			cookie_expire = ap_pregsub(r->pool, "$3", cookie,AP_MAX_REG_MATCH,regmatch);
			cookie_valid = ap_pregsub(r->pool, "$4", cookie,AP_MAX_REG_MATCH,regmatch);
				
if (conf->debugLevel) 
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                      "Found cookie Expires \"%s\" Valid \"%s\"",cookie_expire,cookie_valid);

				if (cookie_expire && cookie_valid && *user) {
					long unsigned int exp = apr_atoi64(cookie_expire);
					long unsigned int now = apr_time_now()/1000000;
					if (exp < now) {

if (conf->debugLevel) 
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
           "Expired. Now=%lu Expire=%lu\n",now,exp);

						return 0;	/* Expired */
					}
					if (!secret) {
						secret = getUserSecret(r,*user,&secretLen,0L);
					}
					char *h = hash_cookie(r->pool,secret,secretLen,exp);

if (conf->debugLevel) 
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                      "Match cookie \"%s\" vs  \"%s\"",h,cookie_valid);

					if (apr_strnatcmp(h,cookie_valid)==0)
						return 1; /* Valid Cookie */
					else {

if (conf->debugLevel) 
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                      "MISMATCHED  cookie \"%s\" vs  \"%s\"",h,cookie_valid);

						return 0; /* Mismatched */
					}
				}
		}
	}
	return 0;	/* Not found */
}
void password_test(apr_pool_t *pool,char *cookie) {
	char *user=0l;
	ap_regmatch_t regmatch[AP_MAX_REG_MATCH];
	printf("will regexec \n");
	if (!ap_regexec(passwd_regexp, cookie, AP_MAX_REG_MATCH, regmatch, 0)) {
		printf("regexec done\n");
		user  = ap_pregsub(pool, "$1", cookie,AP_MAX_REG_MATCH,regmatch);
		printf("PASSWORD GOOD: \"%s\"\n",user);
	} else
		printf ("INVALID PASSWORD: \"%s\"\n",cookie);
}
Ejemplo n.º 8
0
static void dump_content(saxctxt *ctx)
{
    urlmap *m;
    char *found;
    size_t s_from, s_to;
    size_t match;
    char c = 0;
    int nmatch;
    ap_regmatch_t pmatch[10];
    char *subs;
    size_t len, offs;
    urlmap *themap = ctx->map;
#ifndef GO_FASTER
    int verbose = APLOGrtrace1(ctx->f->r);
#endif

    pappend(ctx, &c, 1);        /* append null byte */
        /* parse the text for URLs */
    for (m = themap; m; m = m->next) {
        if (!(m->flags & M_CDATA))
            continue;
        if (m->flags & M_REGEX) {
            nmatch = 10;
            offs = 0;
            while (!ap_regexec(m->from.r, ctx->buf+offs, nmatch, pmatch, 0)) {
                match = pmatch[0].rm_so;
                s_from = pmatch[0].rm_eo - match;
                subs = ap_pregsub(ctx->f->r->pool, m->to, ctx->buf+offs,
                                  nmatch, pmatch);
                s_to = strlen(subs);
                len = strlen(ctx->buf);
                offs += match;
                VERBOSEB(
                    const char *f = apr_pstrndup(ctx->f->r->pool,
                    ctx->buf + offs, s_from);
                    ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, ctx->f->r,
                                  "C/RX: match at %s, substituting %s", f, subs);
                )
                if (s_to > s_from) {
                    preserve(ctx, s_to - s_from);
                    memmove(ctx->buf+offs+s_to, ctx->buf+offs+s_from,
                            len + 1 - s_from - offs);
                    memcpy(ctx->buf+offs, subs, s_to);
                }
                else {
                    memcpy(ctx->buf + offs, subs, s_to);
                    memmove(ctx->buf+offs+s_to, ctx->buf+offs+s_from,
                            len + 1 - s_from - offs);
                }
                offs += s_to;
            }
        }
void cookie_test(apr_pool_t *pool,char *cookie) {
	char *user=0l;
	char *cookie_expire=0l;
	char *cookie_valid=0l;
	ap_regmatch_t regmatch[AP_MAX_REG_MATCH];
	//authn_google_config_rec *conf = ap_get_module_config(r->per_dir_config, &authn_google_module);
	if (!ap_regexec(cookie_regexp, cookie, AP_MAX_REG_MATCH, regmatch, 0)) {
		user  = ap_pregsub(pool, "$2", cookie,AP_MAX_REG_MATCH,regmatch);
		cookie_expire = ap_pregsub(pool, "$3", cookie,AP_MAX_REG_MATCH,regmatch);
		cookie_valid = ap_pregsub(pool, "$4", cookie,AP_MAX_REG_MATCH,regmatch);
		printf("COOKIE GOOD: \"%s\" \"%s\" \"%s\"\n",user,cookie_expire,cookie_valid);
	} else
		printf ("INVALID COOKIE: \"%s\"\n",cookie);
}
Ejemplo n.º 10
0
static int spot_cookie(request_rec *r)
{
    cookie_dir_rec *dcfg = ap_get_module_config(r->per_dir_config,
                                                &usertrack_module);
    const char *cookie_header;
    ap_regmatch_t regm[NUM_SUBS];

    /* Do not run in subrequests */
    if (!dcfg->enabled || r->main) {
        return DECLINED;
    }

    if ((cookie_header = apr_table_get(r->headers_in, "Cookie"))) {
        if (!ap_regexec(dcfg->regexp, cookie_header, NUM_SUBS, regm, 0)) {
            char *cookieval = NULL;
            int err = 0;
            /* Our regexp,
             * ^cookie_name=([^;]+)|;[ \t]+cookie_name=([^;]+)
             * only allows for $1 or $2 to be available. ($0 is always
             * filled with the entire matched expression, not just
             * the part in parentheses.) So just check for either one
             * and assign to cookieval if present. */
            if (regm[1].rm_so != -1) {
                cookieval = ap_pregsub(r->pool, "$1", cookie_header,
                                       NUM_SUBS, regm);
                if (cookieval == NULL)
                    err = 1;
            }
            if (regm[2].rm_so != -1) {
                cookieval = ap_pregsub(r->pool, "$2", cookie_header,
                                       NUM_SUBS, regm);
                if (cookieval == NULL)
                    err = 1;
            }
            if (err) {
                ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, APLOGNO(01499)
                              "Failed to extract cookie value (out of mem?)");
                return HTTP_INTERNAL_SERVER_ERROR;
            }
            /* Set the cookie in a note, for logging */
            apr_table_setn(r->notes, "cookie", cookieval);

            return DECLINED;    /* There's already a cookie, no new one */
        }
    }
    make_cookie(r);
    return OK;                  /* We set our cookie */
}
Ejemplo n.º 11
0
static sqlalias_filter_ret sqlalias_filter(request_rec *r, apr_array_header_t *filters)
{
	int i;
	sqlalias_filter_entry *entries;
	entries = (sqlalias_filter_entry *) filters->elts;

	for (i = 0; i < filters->nelts; i++) {
		sqlalias_filter_entry *filter = &entries[i];

		if(!ap_regexec((ap_regex_t *)filter->regexp, r->uri, 0, NULL, 0)) {
			DEBUG_MSG(r->server, "sqlalias: %s ignored as defined by SQLAliasFilter rule (%s)", r->uri, filter->pattern); 
			return FILTERED_URI;
		}
	}

	return VALID_URI;
}
Ejemplo n.º 12
0
static int is_contenttype_ignored(dosdetector_dir_config *cfg, request_rec *r)
{
    const char *content_type;
    content_type = ap_sub_req_lookup_uri(r->uri, r, NULL)->content_type;

    ap_regmatch_t regmatch[AP_MAX_REG_MATCH];
    ap_regex_t **contenttype_regexp = (ap_regex_t **) cfg->contenttype_regexp->elts;

    int i, ignore = 0;
    for (i = 0; i < cfg->contenttype_regexp->nelts; i++) {
        if(!ap_regexec(contenttype_regexp[i], content_type, AP_MAX_REG_MATCH, regmatch, 0)) {
            ignore = 1;
            break;
        }
    }
    DEBUGLOG_R("content-type=%s, result=%s", content_type, (ignore ? "ignored":"processed"));
    return ignore;
}
static char *getSharedKey(request_rec *r,char *filename, char **static_pw) {
		ap_regmatch_t regmatch[AP_MAX_REG_MATCH];
    char l[MAX_STRING_LEN];
		char *sharedKey = 0L;
		apr_status_t status;
    ap_configfile_t *f;

		authn_google_config_rec *conf = ap_get_module_config(r->per_dir_config, &authn_google_module);
    status = ap_pcfg_openfile(&f, r->pool, filename);
ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
"OPENING FILENAME %s",filename);

    if (status != APR_SUCCESS) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
                      "check_password: Couldn't open password file: %s", filename);
        return 0L;
    }

    while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {

				/* If we have a password entry - return it, if the caller has asked for it */

				if ((static_pw) && (!ap_regexec(passwd_regexp, l, AP_MAX_REG_MATCH, regmatch, 0))) {
					*static_pw  = ap_pregsub(r->pool, "$1", l,AP_MAX_REG_MATCH,regmatch);

if (conf->debugLevel) 
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
           "Using static password \"%s\"",*static_pw);
				}

        /* Skip comment or blank lines. */
        if ((l[0] == '"') || (!l[0])) {
            continue;
        }

				if (!sharedKey) {
					sharedKey = apr_pstrdup(r->pool,l);
				}

				/* Scratch codes to follow */
    }
    ap_cfg_closefile(f);
		return sharedKey;
}
Ejemplo n.º 14
0
extern apr_status_t check_regular_expression(request_rec *r, char *haystack, char *needle) {
    ap_regex_t *regexp = (ap_regex_t *)NULL;
    ap_regmatch_t regmatch[AP_MAX_REG_MATCH];

    // Validation Check
    if (haystack == (char *)NULL) { return DECLINED; }
    if (needle == (char *)NULL) { return DECLINED; }

    if (strlen(haystack) > 0) {
        regexp = (ap_regex_t *)ap_pregcomp(r->pool, (const char *)haystack, REG_EXTENDED|REG_ICASE);
        if (regexp != (ap_regex_t *)NULL &&
            ap_regexec(regexp, (const char*)needle, regexp->re_nsub + 1, regmatch, 0) == 0) {
            ap_pregfree(r->pool, regexp);
            return APR_SUCCESS;
        }
        ap_pregfree(r->pool, regexp);
    }

    return DECLINED;
}
Ejemplo n.º 15
0
static apr_status_t parse_request_uri(request_rec *r, char **uri, char **size)
{
    int            nmatch = 10;
    ap_regmatch_t  match[nmatch];
    ap_regex_t    *reg;

    reg = ap_pregcomp(r->pool, "^/(original|large|medium|small)/(.*)$",
                      AP_REG_EXTENDED);
    if (ap_regexec(reg, r->unparsed_uri, nmatch, match, 0) == 0) {
        *size = ap_pregsub(r->pool, "$1", r->unparsed_uri, nmatch, match);
        *uri  = ap_pregsub(r->pool, "$2", r->unparsed_uri, nmatch, match);
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                      "Parse URI: %s, %s", *size, *uri);
        ap_pregfree(r->pool, reg);

        return APR_SUCCESS;
    }
    else {
        return APR_EGENERAL;
    }
}
Ejemplo n.º 16
0
/* Here-in lies the meat */
static int dosblock_main(request_rec *r) {
    const apr_table_entry_t *dosrulemap_elts = NULL;
    const apr_array_header_t *dosrulemap_arr = NULL;
    char *subrule=NULL, *dosrulematch=NULL, *urlpattern=NULL;
    char *req_header = NULL;
    int matchfound = 0;
    int gotlock = 0;
    dosblockipc_data *base = NULL;
    apr_status_t rs;
    dosblock_cfg *cfg = (dosblock_cfg *)ap_get_module_config(r->server->module_config, &mod_dosblock_module);

    /* Here we try to find if the request matches a dos rule */
    dosrulemap_arr = apr_table_elts(cfg->dosrulemap);

    if (dosrulemap_arr) {
        dosrulemap_elts = (const apr_table_entry_t *)dosrulemap_arr->elts;
        int i;
        for (i=0; i<dosrulemap_arr->nelts; ++i)
         {
           subrule = dosrulemap_elts[i].val;
           char *subrule_type =  (char *)apr_table_get(cfg->ruletype, subrule);
           if (subrule_type == NULL)
             continue;
           /* Check if it is a url based subrule */
           if (0 == apr_strnatcmp(subrule_type, RULEURL))
              {
               urlpattern = (char *)apr_table_get(cfg->urlrules, subrule);
               if (urlpattern == NULL)
                 continue;
               ap_regex_t *pattern = ap_pregcomp(r->pool, urlpattern, AP_REG_EXTENDED);
               if (0 == ap_regexec(pattern, r->uri, 0, NULL, 0))
               /* This is where the dos url subrule would match */
                 {
                   dosrulematch = dosrulemap_elts[i].key;
                   matchfound = 1;
                   break;
                 }
              }
           /* Check if it is a header based subrule */
            else if (0 == apr_strnatcmp(subrule_type, RULEHEADER))
             {
              headerrulestruct *h = NULL;
              h = apr_hash_get(cfg->headerrules, subrule, APR_HASH_KEY_STRING);
              if (h == NULL)
                continue;
              req_header = (char *)apr_table_get(r->headers_in, h->headername);
              if (req_header == NULL)
                continue;
              ap_regex_t *pattern = ap_pregcomp(r->pool, h->headerpattern, AP_REG_EXTENDED);
              if (0 == ap_regexec(pattern, req_header, 0, NULL, 0))
               /* This is where the dos header subrule would match */
                {
                  dosrulematch = dosrulemap_elts[i].key;
                  matchfound = 1;
                  break;
                }
             }
         }
       }

    if (matchfound && dosrulematch) {
      int blocked = 0;
      /* apr_table_set(r->headers_out, "DOSRULE_MATCHED", dosrulematch);*/
      /*  Check if we have the corresponding shared memory segment for
       *  the matching dos rule. If not we do not go further.
       */
      if (!apr_hash_get(cfg->dosrule_shm_map, dosrulematch, APR_HASH_KEY_STRING))
       {
          return DECLINED;
        }
      apr_int64_t index = apr_atoi64(apr_hash_get(cfg->dosrule_shm_map, dosrulematch, APR_HASH_KEY_STRING));

      /* Take the mutex lock here. Be careful of not 'returning' before releasing the lock*/
      rs = apr_global_mutex_lock(dosblockipc_mutex[index]);
      if (APR_SUCCESS == rs) {
          gotlock = 1;
      }
      else {
        /* Some error, log and bail */
        ap_log_error(APLOG_MARK, APLOG_ERR, rs, r->server, "Child %ld failed to acquire lock", (long int)getpid());
      }
      base = (dosblockipc_data *)apr_shm_baseaddr_get(dosblockipc_shm[index]);
      /* check if the Dos rule is already blocked */
      if (base->ds.isblocked)
       {
        /* The dos rule is blocked at this moment. Need to check the time stamp
         * (time till blockage) and act accordingly
         */
        apr_time_t time_now = apr_time_now();
        apr_time_t time_to_blockage = base->ds.t;
        /* apr_table_set(r->headers_out, "Blocked till", apr_psprintf(r->pool, "%d",time_to_blockage)); */
        if(cfg->verbosity)
           ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Dos rule %s is blocked", dosrulematch);
        if (time_now < time_to_blockage)
         {
          /* Keep blocking */
           blocked = 1;
           if(cfg->verbosity)
             ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Keep dos rule %s blocked", dosrulematch);

         }
        else {
          /* Time to unblock */
           base->ds.isblocked = 0;
           base->ds.t = 0;
           /* apr_table_set(r->headers_out, "Time-to-unblock", "Unblock"); */
           if(cfg->verbosity)
             ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Time to unblock dos rule %s", dosrulematch);

          }
      }
      /* Here we age entries, try to account for the matched hit, calculate the
       * rate and take some action if needed.
       */
      int i;
      apr_int64_t sum_counter = 0;
      int hit_accounted = 0;

      /* Loop through the array of structs */
      for (i=0; i<ARSIZE; i++) {
        if (base->dh[i].t) {
          if ((r->request_time - base->dh[i].t)/APR_USEC_PER_SEC > ARSIZE ) {
            /* Ageing entries */
             base->dh[i].t = 0;
             base->dh[i].counter = 0;
             if(cfg->verbosity)
               ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Ageing entry for dos rule %s", dosrulematch);
             continue;
           }
          if (base->dh[i].t/APR_USEC_PER_SEC == r->request_time/APR_USEC_PER_SEC )
            {
              /* There is already an entry for this sec. Increment the corresponding
               * counter
               */
              base->dh[i].counter++;
              sum_counter+= base->dh[i].counter;
              hit_accounted = 1;
              /*apr_table_set(r->headers_out, "Entry-for-this-sec", "Exists"); */
              if(cfg->verbosity)
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "We have an Entry-for-this-sec for dos rule %s", dosrulematch);
             continue;
            }
          sum_counter+= base->dh[i].counter;
          }
        }

      /* Add an element in our array of structs for this second if the hit was not accounted above */
      if (! hit_accounted) {
        if(cfg->verbosity)
          ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Hit is not accounted for dos rule %s", dosrulematch);
        if ((ARSIZE - base->next) ==  0)
          base->next = 0;
        base->dh[base->next].t = r->request_time;
        base->dh[base->next].counter = 1;
        sum_counter+= base->dh[base->next].counter;
        base->next++;
        /*apr_table_set(r->headers_out, "Entry-for-this-sec", "Does-not-Exist");*/
        if(cfg->verbosity)
          ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "We do not have an entry for this second (dos rule %s) and sum of counter is %" APR_INT64_T_FMT, dosrulematch, sum_counter);
      }

      if ( ! blocked) {
        float rate = (float)sum_counter/ARSIZE;
        /* Get the configured rate threshold */
        dosrulestruct *d = apr_hash_get(cfg->dosrules, dosrulematch, APR_HASH_KEY_STRING);
        if(cfg->verbosity) {
          ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Non Blocked dos rule %s sum of counter is %" APR_INT64_T_FMT, dosrulematch, sum_counter);
          ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Non Blocked dos rule %s rate is %f", dosrulematch, rate);
          ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Non Blocked dos rule %s configured  rate is %" APR_INT64_T_FMT, dosrulematch, apr_atoi64(d->threshold));
        }
        if (rate > apr_atoi64(d->threshold))
         {
           /* Block it */
           base->ds.isblocked = 1;
           base->ds.t = (apr_time_now() + (apr_atoi64(d->timetoblock)*APR_USEC_PER_SEC));
           base->ds.rate_when_blocked = rate;
           if(cfg->verbosity) {
             ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Non Blocked dos rule %s getting blocked after rate calulation", dosrulematch);
             ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Non Blocked dos rule %s getting blocked till %" APR_TIME_T_FMT, dosrulematch, base->ds.t);
           }
           blocked = 1;
         }
      }

      /* Release the lock. We have to be careful of not 'returning' before
       * releasing the lock
       */
      if (gotlock)
        rs = apr_global_mutex_unlock(dosblockipc_mutex[index]);
      /* Swallowing the result because what are we going to do with it at
       * this stage
       */
      if (blocked)
        return HTTP_SERVICE_UNAVAILABLE;
   }
    else {
      /* apr_table_set(r->headers_out, "DOSRULE_MATCHED", "None");*/
    }

    return DECLINED;
}
Ejemplo n.º 17
0
static void do_pattmatch(ap_filter_t *f, apr_bucket *inb,
                         apr_bucket_brigade *mybb,
                         apr_pool_t *tmp_pool)
{
    int i;
    int force_quick = 0;
    ap_regmatch_t regm[AP_MAX_REG_MATCH];
    apr_size_t bytes;
    apr_size_t len;
    apr_size_t fbytes;
    const char *buff;
    const char *repl;
    char *scratch;
    char *p;
    char *s1;
    char *s2;
    apr_bucket *b;
    apr_bucket *tmp_b;
    apr_pool_t *tpool;

    subst_dir_conf *cfg =
    (subst_dir_conf *) ap_get_module_config(f->r->per_dir_config,
                                             &substitute_module);
    subst_pattern_t *script;

    APR_BRIGADE_INSERT_TAIL(mybb, inb);
    
    script = (subst_pattern_t *) cfg->patterns->elts;
    apr_pool_create(&tpool, tmp_pool);
    scratch = NULL;
    fbytes = 0;
    /*
     * Simple optimization. If we only have one pattern, then
     * we can safely avoid the overhead of flattening
     */
    if (cfg->patterns->nelts == 1) {
       force_quick = 1;
    }
    for (i = 0; i < cfg->patterns->nelts; i++) {
        for (b = APR_BRIGADE_FIRST(mybb);
             b != APR_BRIGADE_SENTINEL(mybb);
             b = APR_BUCKET_NEXT(b)) {
            if (APR_BUCKET_IS_METADATA(b)) {
                /*
                 * we should NEVER see this, because we should never
                 * be passed any, but "handle" it just in case.
                 */
                continue;
            }
            if (apr_bucket_read(b, &buff, &bytes, APR_BLOCK_READ)
                    == APR_SUCCESS) {
                s1 = NULL;
                if (script->pattern) {
                    while ((repl = apr_strmatch(script->pattern, buff, bytes)))
                    {
                        /* get offset into buff for pattern */
                        len = (apr_size_t) (repl - buff);
                        if (script->flatten && !force_quick) {
                            /*
                             * We are flattening the buckets here, meaning
                             * that we don't do the fast bucket splits.
                             * Instead we copy over what the buckets would
                             * contain and use them. This is slow, since we
                             * are constanting allocing space and copying
                             * strings.
                             */
                            SEDSCAT(s1, s2, tmp_pool, buff, len,
                                    script->replacement);
                        }
                        else {
                            /*
                             * We now split off the stuff before the regex
                             * as its own bucket, then isolate the pattern
                             * and delete it.
                             */
                            SEDRMPATBCKT(b, len, tmp_b, script->patlen);
                            /*
                             * Finally, we create a bucket that contains the
                             * replacement...
                             */
                            tmp_b = apr_bucket_transient_create(script->replacement,
                                      script->replen,
                                      f->r->connection->bucket_alloc);
                            /* ... and insert it */
                            APR_BUCKET_INSERT_BEFORE(b, tmp_b);
                        }
                        /* now we need to adjust buff for all these changes */
                        len += script->patlen;
                        bytes -= len;
                        buff += len;
                    }
                    if (script->flatten && s1 && !force_quick) {
                        /*
                         * we've finished looking at the bucket, so remove the
                         * old one and add in our new one
                         */
                        s2 = apr_pstrmemdup(tmp_pool, buff, bytes);
                        s1 = apr_pstrcat(tmp_pool, s1, s2, NULL);
                        tmp_b = apr_bucket_transient_create(s1, strlen(s1),
                                            f->r->connection->bucket_alloc);
                        APR_BUCKET_INSERT_BEFORE(b, tmp_b);
                        apr_bucket_delete(b);
                        b = tmp_b;
                    }

                }
                else if (script->regexp) {
                    /*
                     * we need a null terminated string here :(. To hopefully
                     * save time and memory, we don't alloc for each run
                     * through, but only if we need to have a larger chunk
                     * to save the string to. So we keep track of how much
                     * we've allocated and only re-alloc when we need it.
                     * NOTE: this screams for a macro.
                     */
                    if (!scratch || (bytes > (fbytes + 1))) {
                        fbytes = bytes + 1;
                        scratch = apr_palloc(tpool, fbytes);
                    }
                    /* reset pointer to the scratch space */
                    p = scratch;
                    memcpy(p, buff, bytes);
                    p[bytes] = '\0';
                    while (!ap_regexec(script->regexp, p,
                                       AP_MAX_REG_MATCH, regm, 0)) {
                        /* first, grab the replacement string */
                        repl = ap_pregsub(tmp_pool, script->replacement, p,
                                          AP_MAX_REG_MATCH, regm);
                        if (script->flatten && !force_quick) {
                            SEDSCAT(s1, s2, tmp_pool, p, regm[0].rm_so, repl);
                        }
                        else {
                            len = (apr_size_t) (regm[0].rm_eo - regm[0].rm_so);
                            SEDRMPATBCKT(b, regm[0].rm_so, tmp_b, len);
                            tmp_b = apr_bucket_transient_create(repl,
                                                                strlen(repl),
                                             f->r->connection->bucket_alloc);
                            APR_BUCKET_INSERT_BEFORE(b, tmp_b);
                        }
                        /*
                         * reset to past what we just did. buff now maps to b
                         * again
                         */
                        p += regm[0].rm_eo;
                    }
                    if (script->flatten && s1 && !force_quick) {
                        s1 = apr_pstrcat(tmp_pool, s1, p, NULL);
                        tmp_b = apr_bucket_transient_create(s1, strlen(s1),
                                            f->r->connection->bucket_alloc);
                        APR_BUCKET_INSERT_BEFORE(b, tmp_b);
                        apr_bucket_delete(b);
                        b = tmp_b;
                    }

                }
                else {
                    /* huh? */
                    continue;
                }
            }
        }
        script++;
    }

    apr_pool_destroy(tpool);

    return;
}
Ejemplo n.º 18
0
static void pstartElement(void *ctxt, const xmlChar * uname, const xmlChar ** uattrs)
{
  int num_match;
  char *subs;
  int is_uri;
  const char **a;
  size_t s_to, s_from;
  saxctxt *ctx = (saxctxt *) ctxt;
  apr_array_header_t *linkattrs;
  int i;
  const char *name = (const char *) uname;
  const char **attrs = (const char **) uattrs;
  const htmlElemDesc *desc = htmlTagLookup(uname);

  /* VoxCDN FIXME: rewrite this, it's ridiculously bad */

#if 0 /* for now, err on the side of leaving stuff alone */
  int enforce = 0;
  if ((ctx->cfg->doctype == fpi_html) || (ctx->cfg->doctype == fpi_xhtml)) {
    /* enforce html */
    enforce = 2;
    if (!desc || desc->depr)
      return;

  } else if ((ctx->cfg->doctype == fpi_html)
		|| (ctx->cfg->doctype == fpi_xhtml)) {
    enforce = 1;
    /* enforce html legacy */
    if (!desc) {
      return;
    }
  }
  if (!desc && enforce) {
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->f->r,
		"Bogus HTML element %s dropped", name) ;
    return;
  }
  if (desc && desc->depr && (enforce == 2) ) {
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->f->r,
		"Deprecated HTML element %s dropped", name) ;
    return;
  }
#endif

  ap_fputc(ctx->f->next, ctx->bb, '<');
  ap_fputs(ctx->f->next, ctx->bb, name);

  if (attrs) {
    linkattrs =
      apr_hash_get(ctx->cfg->links, name, APR_HASH_KEY_STRING);
    for (a = attrs; *a; a += 2) {
      ctx->offset = 0;
      if (a[1]) {
        pappend(ctx, a[1], strlen(a[1]) + 1);
        is_uri = 0;
        if (linkattrs) {
          tattr *attrs = (tattr *) linkattrs->elts;
          for (i = 0; i < linkattrs->nelts; ++i) {
            if (!strcmp(*a, attrs[i].val)) {
              is_uri = 1;
              break;
            }
          }
        }

        if(is_uri) {
          /* first do the server replacements */
          if(ctx->cfg->map) {
            server_remap_t *remaps = (server_remap_t *)ctx->cfg->map->elts;
            for(i = 0; i < ctx->cfg->map->nelts; ++i) {
              if(!ap_regexec(&(remaps[i].regex), ctx->buf, 0, 0, 0)) {
                int add_auth = ctx->cfg->global_auth | (remaps[i].flags & REMAP_FLAG_AUTH);
                int add_qstring_ignore =
                  ctx->cfg->global_qstring_ignore | (remaps[i].flags & REMAP_FLAG_QSTRING_IGNORE);
                subs = remap_url(ctx, ctx->buf, add_auth, add_qstring_ignore);
                if(subs) {
                  ++num_match;
                  s_to = strlen(subs);
                  s_from = strlen(ctx->buf);
                  if(s_to > s_from)
                    preserve(ctx, s_to - s_from);
                  memcpy(ctx->buf, subs, s_to+1);
                  break; /* only do one substitution per link */
                }
              }
            }
          }
        }
      }
      if (!a[1])
        ap_fputstrs(ctx->f->next, ctx->bb, " ", a[0], NULL);
      else {
        /* write the attribute */
        ap_fputstrs(ctx->f->next, ctx->bb, " ", a[0], "=\"", NULL);
        pcharacters(ctx, (const xmlChar *) ctx->buf, strlen(ctx->buf));
        ap_fputc(ctx->f->next, ctx->bb, '"');
      }
    }
  }
  ctx->offset = 0;
  if(desc && desc->empty)
    ap_fputs(ctx->f->next, ctx->bb, "/>");
  else
    ap_fputc(ctx->f->next, ctx->bb, '>');
}
Ejemplo n.º 19
0
/*
 *  Get the stuff from LDAP
 */
static int getldaphome(request_rec *r, vhx_config_rec *vhr, const char *hostname, vhx_request_t *reqc)
{
	/* LDAP associated variable and stuff */
	const char 		**vals = NULL;
	char 			*filtbuf = NULL;
	int 			result = 0;
	const char 		*dn = NULL;
	util_ldap_connection_t 	*ldc = NULL;
	int 			failures = 0;

	VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "getldaphome(): BEGIN ***,pid=%d",getpid());


	/* Check for illegal characters in hostname that would mess up the LDAP query */
	ap_regex_t *cpat = ap_pregcomp(r->pool, "\\[\\/\\*\\(\\)&\\]", REG_EXTENDED|REG_ICASE); 
	if(cpat != NULL) {
		if (ap_regexec(cpat, hostname, 0, NULL, 0) == 0 ) {
			VH_AP_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, "%s: (getldaphome) bad characters in hostname %s", VH_NAME, hostname);
			return DECLINED;
		}
	}

start_over:

	if (vhr->ldap_host) {
		VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "getldaphome(): util_ldap_connection_find(r,%s,%d,%s,%s,%d,%d);",vhr->ldap_host, vhr->ldap_port, vhr->ldap_binddn, vhr->ldap_bindpw, vhr->ldap_deref, vhr->ldap_secure);
		ldc = util_ldap_connection_find(r, vhr->ldap_host, vhr->ldap_port, vhr->ldap_binddn,
				vhr->ldap_bindpw, vhr->ldap_deref, vhr->ldap_secure);
	} else {
		return DECLINED;
	}

	filtbuf = apr_psprintf(r->pool, "(&(%s)(|(apacheServerName=%s)(apacheServerAlias=%s)))", vhr->ldap_filter, hostname, hostname);

	VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "getldaphome(): filtbuf = %s",filtbuf);
	//VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "getldaphome(): %s %s %d %s %s",vhr->ldap_url,vhr->ldap_basedn,vhr->ldap_scope,ldap_attributes[0],filtbuf);

	result = util_ldap_cache_getuserdn(r, ldc, vhr->ldap_url, vhr->ldap_basedn, vhr->ldap_scope, ldap_attributes, filtbuf, &dn, &vals);
	util_ldap_connection_close(ldc);

	// sanity check - if server is down, retry it up to 5 times 
	if (result == LDAP_SERVER_DOWN) {
		if (failures++ <= 5) {
			apr_sleep(1000000);
			goto start_over;
		}
	}
	if ((result == LDAP_NO_SUCH_OBJECT)) {
		VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r,
				"getldaphome(): virtual host %s not found",
				hostname);
		return DECLINED;
	}

	/* handle bind failure */
	if (result != LDAP_SUCCESS) {
		VH_AP_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r,
				"%s: (getldaphome) translate failed; virtual host %s; URI %s LDAP Error: [%s]", 
				VH_NAME, hostname, r->uri, ldap_err2string(result));
		return DECLINED;
	}

	int i = 0;
	while (ldap_attributes[i]) {
		if (apr_strnatcasecmp (ldap_attributes[i], "apacheServerName") == 0) {
			reqc->name = apr_pstrdup (r->pool, vals[i]);
		}
		else if (apr_strnatcasecmp (ldap_attributes[i], "apacheServerAdmin") == 0) {
			reqc->admin = apr_pstrdup (r->pool, vals[i]);
		}
		else if (apr_strnatcasecmp (ldap_attributes[i], "apacheDocumentRoot") == 0) {
			reqc->docroot = apr_pstrdup (r->pool, vals[i]);
		}
		else if (apr_strnatcasecmp (ldap_attributes[i], "homeDirectory") == 0) {
			reqc->homedirectory = apr_pstrdup (r->pool, vals[i]);
		}
		else if (apr_strnatcasecmp (ldap_attributes[i], "phpOptions") == 0) {
			reqc->phpoptions = apr_pstrdup (r->pool, vals[i]);
		}
		else if (apr_strnatcasecmp (ldap_attributes[i], "uidNumber") == 0) {
			reqc->uid = apr_pstrdup(r->pool, vals[i]);
		}
		else if (apr_strnatcasecmp (ldap_attributes[i], "gidNumber") == 0) {
			reqc->gid = apr_pstrdup(r->pool, vals[i]);
		}
		else if (apr_strnatcasecmp (ldap_attributes[i], "apacheChrootDir") == 0) {
			reqc->chroot_dir = apr_pstrdup(r->pool, vals[i]);
		}
		i++;
	}

	reqc->vhost_found = VH_VHOST_INFOS_FOUND;

	VH_AP_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, "getldaphome(): END ***");

	/* If we don't have a document root then we can't honour the request */
	if (reqc->docroot == NULL) {
		VH_AP_LOG_RERROR(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, "%s: (getldaphome) no document root found for %s", VH_NAME, hostname);
		return DECLINED;
	}

	/* We have a document root so, this is ok */
	return OK;
}
// Find the cookie and figure out what to do
static int spot_cookie(request_rec *r)
{
    cookietrack_settings_rec *dcfg = ap_get_module_config(r->per_dir_config,
                                                &cookietrack_module);

    const char *cookie_header;
    ap_regmatch_t regm[NUM_SUBS];

    /* Do not run in subrequests */
    if (!dcfg->enabled || r->main) {
        return DECLINED;
    }

    /* Is DNT set? */
    const char *dnt_is_set = apr_table_get( r->headers_in, "DNT" );
    _DEBUG && fprintf( stderr, "DNT: %s\n", dnt_is_set );

    /* Do we already have a cookie? */
    char *cur_cookie_value = NULL;
    if( (cookie_header = apr_table_get(r->headers_in, "Cookie")) ){

        // this will match the FIRST occurance of the cookiename, not
        // subsequent ones.
        if( !ap_regexec(dcfg->regexp, cookie_header, NUM_SUBS, regm, 0) ) {
            /* Our regexp,
             * ^cookie_name=([^;]+)|;[ \t]+cookie_name=([^;]+)
             * only allows for $1 or $2 to be available. ($0 is always
             * filled with the entire matched expression, not just
             * the part in parentheses.) So just check for either one
             * and assign to cookieval if present. */
            if( regm[1].rm_so != -1 ) {
                cur_cookie_value = ap_pregsub(r->pool, "$1", cookie_header,
                                       NUM_SUBS, regm);
            }
            if( regm[2].rm_so != -1 ) {
                cur_cookie_value = ap_pregsub(r->pool, "$2", cookie_header,
                                       NUM_SUBS, regm);
            }
        }
    }

    _DEBUG && fprintf( stderr, "Current Cookie: %s\n", cur_cookie_value );

    /* XFF support inspired by this patch:
       http://www.mail-archive.com/[email protected]/msg17378.html

       And this implementation for scanning for remote ip:
       http://apache.wirebrain.de/lxr/source/modules/metadata/mod_remoteip.c?v=2.3-trunk#267
    */

    // Get the IP address of the originating request
    const char *rname = NULL;   // Originating IP address
    char *xff         = NULL;   // X-Forwarded-For, or equivalent header type

    // Should we look at a header?
    if( xff = apr_table_get(r->headers_in, dcfg->cookie_ip_header) ) {

        // There might be multiple addresses in the header
        // Check if there's a comma in there somewhere

        // no comma, this is the address we can use
        if( (rname = strrchr(xff, ',')) == NULL ) {
            rname = xff;

        // whitespace/commas left, remove 'm
        } else {

            // move past the comma
            rname++;

            // and any whitespace we might find
            while( *rname == ' ' ) {
                rname++;
            }
        }

    // otherwise, get it from the remote host
    } else {
        rname = ap_get_remote_host( r->connection, r->per_dir_config,
                                    REMOTE_NAME, NULL );
    }

    _DEBUG && fprintf( stderr, "Remote Address: %s\n", rname );

    /* Determine the value of the cookie we're going to set: */
    /* Make sure we have enough room here... */
    char new_cookie_value[ _MAX_COOKIE_LENGTH ];

    // dnt is set, and we care about that
    if( dnt_is_set && dcfg->comply_with_dnt ) {

        // you don't want us to set a cookie, alright then our work is done.
        if( !dcfg->set_dnt_cookie ) {
            return DECLINED;
        }

        char *dnt_value = dcfg->dnt_value;

        // you already ahve a cookie, but it might be whitelisted
        if( cur_cookie_value ) {

            // you might have whitelisted this value; let's check
            // Following tutorial code here again:
            // http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-19.html
            int i;
            for( i = 0; i < dcfg->dnt_exempt->nelts; i++ ) {
                _DEBUG && fprintf( stderr, "e: %d\n", i );

                char *exempt = ((char **)dcfg->dnt_exempt->elts)[i];

                //it's indeed whiteliested, we should use this value instead
                if( strcasecmp( cur_cookie_value, exempt ) == 0 ) {
                    _DEBUG && fprintf( stderr,
                        "Cookie %s is DNT exempt\n", cur_cookie_value );

                    dnt_value = exempt;
                }
            }
        }

        // dnt_value is a pointer, hence the sprintf
        sprintf( new_cookie_value, "%s", dnt_value );

    // No DNT header, so we need a cookie value to set
    } else {

        // there already is a cookie set
        if( cur_cookie_value ) {

            // but it's set to the DNT cookie
            if( strcasecmp( cur_cookie_value, dcfg->dnt_value ) == 0 ) {

                // if we have some sort of library that's generating the
                // UID, call that with the cookie we would be setting
                if( _EXTERNAL_UID_FUNCTION ) {
                    char ts[ _MAX_COOKIE_LENGTH ];
                    sprintf( ts, "%" APR_TIME_T_FMT, apr_time_now() );
                    gen_uid( new_cookie_value, ts, rname );

                // otherwise, just set it
                } else {
                    sprintf( new_cookie_value,
                             "%s.%" APR_TIME_T_FMT, rname, apr_time_now() );
                }

            // it's set to something reasonable - note we're still setting
            // a new cookie, even when there's no expires requested, because
            // we don't know if there's an expires on the /current/ cookie.
            // this could be added, but this seems to work for now.
            } else {
                // XXX we use a apr_pstrndup instead, so we can't overflow
                // the buffer if we get sent garbage
                // The return value is a
                sprintf( new_cookie_value, "%s",
                    apr_pstrndup( r->pool, cur_cookie_value, _MAX_COOKIE_LENGTH ) );

            }

        // it's either carbage, or not set; either way,
        // we need to generate a new one
        } else {
            // if we have some sort of library that's generating the
            // UID, call that with the cookie we would be setting
            if( _EXTERNAL_UID_FUNCTION ) {
                char ts[ _MAX_COOKIE_LENGTH ];
                sprintf( ts, "%" APR_TIME_T_FMT, apr_time_now() );
                gen_uid( new_cookie_value, ts, rname );

            // otherwise, just set it
            } else {
                sprintf( new_cookie_value,
                         "%s.%" APR_TIME_T_FMT, rname, apr_time_now() );
            }
        }
    }

    _DEBUG && fprintf( stderr, "New cookie: %s\n", new_cookie_value );

    /* Set the cookie in a note, for logging */
    apr_table_setn(r->notes, dcfg->note_name, new_cookie_value);

    make_cookie(r,  new_cookie_value,
                    cur_cookie_value,
                    (dnt_is_set && dcfg->comply_with_dnt)   // should we use dnt expires?
                );

    // We need to flush the stream for messages to appear right away.
    // Performing an fflush() in a production system is not good for
    // performance - don't do this for real.
    _DEBUG && fflush(stderr);

    return OK;                  /* We set our cookie */
}
static apr_status_t line_edit_filter(ap_filter_t* f, apr_bucket_brigade* bb) {
  int i, j;
  unsigned int match ;
  unsigned int nmatch = 10 ;
  ap_regmatch_t pmatch[10] ;
  const char* bufp;
  const char* subs ;
  apr_size_t bytes ;
  apr_size_t fbytes ;
  apr_size_t offs ;
  const char* buf ;
  const char* le = NULL ;
  const char* le_n ;
  const char* le_r ;
  char* fbuf ;
  apr_bucket* b = APR_BRIGADE_FIRST(bb) ;
  apr_bucket* b1 ;
  int found = 0 ;
  apr_status_t rv ;

  apr_bucket_brigade* bbline ;
  line_edit_cfg* cfg
	= ap_get_module_config(f->r->per_dir_config, &line_edit_module) ;
  rewriterule* rules = (rewriterule*) cfg->rewriterules->elts ;
  rewriterule* newrule;

  line_edit_ctx* ctx = f->ctx ;
  if (ctx == NULL) {

    /* check env to see if we're wanted, to give basic control with 2.0 */
    buf = apr_table_get(f->r->subprocess_env, "LineEdit");
    if (buf && f->r->content_type) {
      char* lcbuf = apr_pstrdup(f->r->pool, buf) ;
      char* lctype = apr_pstrdup(f->r->pool, f->r->content_type) ;
      char* c ;

      for (c = lcbuf; *c; ++c)
	if (isupper(*c))
	  *c = tolower(*c) ;

      for (c = lctype; *c; ++c)
	if (isupper(*c))
	  *c = tolower(*c) ;
	else if (*c == ';') {
	  *c = 0 ;
	  break ;
	}

      if (!strstr(lcbuf, lctype)) {
	/* don't filter this content type */
	ap_filter_t* fnext = f->next ;
	ap_remove_output_filter(f) ;
	return ap_pass_brigade(fnext, bb) ;
      }
    }

    ctx = f->ctx = apr_palloc(f->r->pool, sizeof(line_edit_ctx)) ;
    ctx->bbsave = apr_brigade_create(f->r->pool, f->c->bucket_alloc) ;

    /* If we have any regex matches, we'll need to copy everything, so we
     * have null-terminated strings to parse.  That's a lot of memory if
     * we're streaming anything big.  So we'll use (and reuse) a local
     * subpool.  Fall back to the request pool if anything bad happens.
     */
    ctx->lpool = f->r->pool ;
    for (i = 0; i < cfg->rewriterules->nelts; ++i) {
      if ( rules[i].flags & M_REGEX ) {
        if (apr_pool_create(&ctx->lpool, f->r->pool) != APR_SUCCESS) {
	  ctx->lpool = f->r->pool ;
        }
        break ;
      }
    }
    /* If we have env interpolation, we'll need a private copy of
     * our rewrite rules with this requests env.  Otherwise we can
     * save processing time by using the original.
     *
     * If one ENV is found, we also have to copy all previous and
     * subsequent rules, even those with no interpolation.
     */
    ctx->rewriterules = cfg->rewriterules;
    for (i = 0; i < cfg->rewriterules->nelts; ++i) {
      found |= (rules[i].flags & M_ENV) ;
      if ( found ) {
	if (ctx->rewriterules == cfg->rewriterules) {
	  ctx->rewriterules = apr_array_make(f->r->pool,
		cfg->rewriterules->nelts, sizeof(rewriterule));
	  for (j = 0; j < i; ++j) {
            newrule = apr_array_push (((line_edit_ctx*)ctx)->rewriterules) ;
	    newrule->from = rules[j].from;
	    newrule->to = rules[j].to;
	    newrule->flags = rules[j].flags;
	    newrule->length = rules[j].length;
	  }
	}
	/* this rule needs to be interpolated */
        newrule = apr_array_push (((line_edit_ctx*)ctx)->rewriterules) ;
	newrule->from = rules[i].from;
	if (rules[i].flags & M_ENV) {
	  newrule->to = interpolate_env(f->r, rules[i].to);
	} else {
	  newrule->to = rules[i].to ;
	}
	newrule->flags = rules[i].flags;
	newrule->length = rules[i].length;
      }
    }
    /* for back-compatibility with Apache 2.0, set some protocol stuff */
    apr_table_unset(f->r->headers_out, "Content-Length") ;
    apr_table_unset(f->r->headers_out, "Content-MD5") ;
    apr_table_unset(f->r->headers_out, "Accept-Ranges") ;
  }
  /* by now our rules are in ctx->rewriterules */
  rules = (rewriterule*) ctx->rewriterules->elts ;

  /* bbline is what goes to the next filter,
   * so we (can) have a new one each time.
   */
  bbline = apr_brigade_create(f->r->pool, f->c->bucket_alloc) ;

  /* first ensure we have no mid-line breaks that might be in the
   * middle of a search string causing us to miss it!  At the same
   * time we split into lines to avoid pattern-matching over big
   * chunks of memory.
   */
  while ( b != APR_BRIGADE_SENTINEL(bb) ) {
    if ( !APR_BUCKET_IS_METADATA(b) ) {
      if ( apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) == APR_SUCCESS ) {
	if ( bytes == 0 ) {
	  APR_BUCKET_REMOVE(b) ;
	} else while ( bytes > 0 ) {
	  switch (cfg->lineend) {

	  case LINEEND_UNIX:
	    le = memchr(buf, '\n', bytes) ;
	    break ;

	  case LINEEND_MAC:
	    le = memchr(buf, '\r', bytes) ;
	    break ;

	  case LINEEND_DOS:
	    /* Edge-case issue: if a \r\n spans buckets it'll get missed.
	     * Not a problem for present purposes, but would be an issue
	     * if we claimed to support pattern matching on the lineends.
	     */
	    found = 0 ;
	    le = memchr(buf+1, '\n', bytes-1) ;
	    while ( le && !found ) {
	      if ( le[-1] == '\r' ) {
	        found = 1 ;
	      } else {
	        le = memchr(le+1, '\n', bytes-1 - (le+1 - buf)) ;
	      }
	    }
	    if ( !found )
	      le = 0 ;
	    break;

	  case LINEEND_ANY:
	  case LINEEND_UNSET:
	    /* Edge-case notabug: if a \r\n spans buckets it'll get seen as
	     * two line-ends.  It'll insert the \n as a one-byte bucket.
	     */
	    le_n = memchr(buf, '\n', bytes) ;
	    le_r = memchr(buf, '\r', bytes) ;
	    if ( le_n != NULL )
	      if ( le_n == le_r + sizeof(char))
	        le = le_n ;
	      else if ( (le_r < le_n) && (le_r != NULL) )
	        le = le_r ;
	      else
	        le = le_n ;
	    else
	      le = le_r ;
	    break;

	  case LINEEND_NONE:
	    le = 0 ;
	    break;

	  case LINEEND_CUSTOM:
	    le = memchr(buf, cfg->lechar, bytes) ;
	    break;
	  }
	  if ( le ) {
	    /* found a lineend in this bucket. */
	    offs = 1 + ((unsigned int)le-(unsigned int)buf) / sizeof(char) ;
	    apr_bucket_split(b, offs) ;
	    bytes -= offs ;
	    buf += offs ;
	    b1 = APR_BUCKET_NEXT(b) ;
	    APR_BUCKET_REMOVE(b);

	    /* Is there any previous unterminated content ? */
	    if ( !APR_BRIGADE_EMPTY(ctx->bbsave) ) {
	      /* append this to any content waiting for a lineend */
	      APR_BRIGADE_INSERT_TAIL(ctx->bbsave, b) ;
	      rv = apr_brigade_pflatten(ctx->bbsave, &fbuf, &fbytes, f->r->pool) ;
	      /* make b a new bucket of the flattened stuff */
	      b = apr_bucket_pool_create(fbuf, fbytes, f->r->pool,
			f->r->connection->bucket_alloc) ;

	      /* bbsave has been consumed, so clear it */
	      apr_brigade_cleanup(ctx->bbsave) ;
	    }
	    /* b now contains exactly one line */
	    APR_BRIGADE_INSERT_TAIL(bbline, b);
	    b = b1 ;
	  } else {
	    /* no lineend found.  Remember the dangling content */
	    APR_BUCKET_REMOVE(b);
	    APR_BRIGADE_INSERT_TAIL(ctx->bbsave, b);
	    bytes = 0 ;
	  }
	} /* while bytes > 0 */
      } else {
	/* bucket read failed - oops !  Let's remove it. */
	APR_BUCKET_REMOVE(b);
      }
    } else if ( APR_BUCKET_IS_EOS(b) ) {
      /* If there's data to pass, send it in one bucket */
      if ( !APR_BRIGADE_EMPTY(ctx->bbsave) ) {
        rv = apr_brigade_pflatten(ctx->bbsave, &fbuf, &fbytes, f->r->pool) ;
        b1 = apr_bucket_pool_create(fbuf, fbytes, f->r->pool,
		f->r->connection->bucket_alloc) ;
        APR_BRIGADE_INSERT_TAIL(bbline, b1);
      }
      apr_brigade_cleanup(ctx->bbsave) ;
      /* start again rather than segfault if a seriously buggy
       * filter in front of us sent a bogus EOS
       */
      f->ctx = NULL ;

      /* move the EOS to the new brigade */
      APR_BUCKET_REMOVE(b);
      APR_BRIGADE_INSERT_TAIL(bbline, b);
    } else {
      /* chop flush or unknown metadata bucket types */
      apr_bucket_delete(b);
    }
    /* OK, reset pointer to what's left (since we're not in a for-loop) */
    b = APR_BRIGADE_FIRST(bb) ;
  }

  /* OK, now we have a bunch of complete lines in bbline,
   * so we can apply our edit rules
   */

  /* When we get a match, we split the line into before+match+after.
   * To flatten that back into one buf every time would be inefficient.
   * So we treat it as three separate bufs to apply future rules.
   *
   * We can only reasonably do that by looping over buckets *inside*
   * the loop over rules.
   *
   * That means concepts like one-match-per-line or start-of-line-only
   * won't work, except for the first rule.  So we won't pretend.
   */
  for (i = 0; i < ctx->rewriterules->nelts; ++i) {
    for ( b = APR_BRIGADE_FIRST(bbline) ;
	b != APR_BRIGADE_SENTINEL(bbline) ;
	b = APR_BUCKET_NEXT(b) ) {
      if ( !APR_BUCKET_IS_METADATA(b)
	&& (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) == APR_SUCCESS)) {
	if ( rules[i].flags & M_REGEX ) {
	  bufp = apr_pstrmemdup(ctx->lpool, buf, bytes) ;
	  while ( ! ap_regexec(rules[i].from.r, bufp, nmatch, pmatch, 0) ) {
	    match = pmatch[0].rm_so ;
	    subs = ap_pregsub(f->r->pool, rules[i].to, bufp, nmatch, pmatch) ;
	    apr_bucket_split(b, match) ;
	    b1 = APR_BUCKET_NEXT(b) ;
	    apr_bucket_split(b1, pmatch[0].rm_eo - match) ;
	    b = APR_BUCKET_NEXT(b1) ;
	    apr_bucket_delete(b1) ;
	    b1 = apr_bucket_pool_create(subs, strlen(subs), f->r->pool,
		  f->r->connection->bucket_alloc) ;
	    APR_BUCKET_INSERT_BEFORE(b, b1) ;
	    bufp += pmatch[0].rm_eo ;
	  }
	} else {
	  bufp = buf ;
	  while (subs = apr_strmatch(rules[i].from.s, bufp, bytes),
			subs != NULL) {
	    match = ((unsigned int)subs - (unsigned int)bufp) / sizeof(char) ;
	    bytes -= match ;
	    bufp += match ;
	    apr_bucket_split(b, match) ;
	    b1 = APR_BUCKET_NEXT(b) ;
	    apr_bucket_split(b1, rules[i].length) ;
	    b = APR_BUCKET_NEXT(b1) ;
	    apr_bucket_delete(b1) ;
	    bytes -= rules[i].length ;
	    bufp += rules[i].length ;
	    b1 = apr_bucket_immortal_create(rules[i].to, strlen(rules[i].to),
		f->r->connection->bucket_alloc) ;
	    APR_BUCKET_INSERT_BEFORE(b, b1) ;
	  }
	}
      }
    }
    /* If we used a local pool, clear it now */
    if ( (ctx->lpool != f->r->pool) && (rules[i].flags & M_REGEX) ) {
      apr_pool_clear(ctx->lpool) ;
    }
  }

  /* now pass it down the chain */
  rv = ap_pass_brigade(f->next, bbline) ;

  /* if we have leftover data, don't risk it going out of scope */
  for ( b = APR_BRIGADE_FIRST(ctx->bbsave) ;
	b != APR_BRIGADE_SENTINEL(ctx->bbsave) ;
	b = APR_BUCKET_NEXT(b)) {
    apr_bucket_setaside(b, f->r->pool) ;
  }

  return rv ;
}
static apr_status_t google_analytics_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
{
    request_rec *r = f->r;
    google_analytics_filter_ctx *ctx = f->ctx;
    google_analytics_filter_config *c;

    apr_bucket *b = APR_BRIGADE_FIRST(bb);

    apr_size_t bytes;
    apr_size_t fbytes;
    apr_size_t offs;
    const char *buf;
    const char *le = NULL;
    const char *le_n;
    const char *le_r;

    const char *bufp;
    const char *subs;
    unsigned int match;

    apr_bucket *b1;
    char *fbuf;
    int found = 0;
    apr_status_t rv;

    apr_bucket_brigade *bbline;
    
    // サブリクエストならなにもしない
    if (r->main) {
        ap_remove_output_filter(f);
        return ap_pass_brigade(f->next, bb);
    }

    c = ap_get_module_config(r->per_dir_config, &google_analytics_module);

    if (ctx == NULL) {
        ctx = f->ctx = apr_pcalloc(r->pool, sizeof(google_analytics_filter_ctx));
        ctx->bbsave = apr_brigade_create(r->pool, f->c->bucket_alloc);
    }

    // length かわってしまうので unset で OK?
    apr_table_unset(r->headers_out, "Content-Length");
    apr_table_unset(r->headers_out, "Content-MD5");
    apr_table_unset(r->headers_out, "Accept-Ranges");
    apr_table_unset(r->headers_out, "ETag");

    bbline = apr_brigade_create(r->pool, f->c->bucket_alloc);
    
    // 改行毎なbucketに編成しなおす
    while ( b != APR_BRIGADE_SENTINEL(bb) ) {
        if ( !APR_BUCKET_IS_METADATA(b) ) {
            if ( apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) == APR_SUCCESS ) {
                if ( bytes == 0 ) {
                    APR_BUCKET_REMOVE(b);
                } else {
					while ( bytes > 0 ) {
						le_n = memchr(buf, '\n', bytes);
                        le_r = memchr(buf, '\r', bytes);
                        if ( le_n != NULL ) {
                            if ( le_n == le_r + sizeof(char)) {
                                le = le_n;
                            }
                            else if ( (le_r < le_n) && (le_r != NULL) ) {
                                le = le_r;
                            }
                            else {
                                le = le_n;
                            }
                        }
                        else {
                            le = le_r;
                        }

                        if ( le ) {
                            offs = 1 + ((unsigned int)le-(unsigned int)buf) / sizeof(char);
                            apr_bucket_split(b, offs);
                            bytes -= offs;
                            buf += offs;
                            b1 = APR_BUCKET_NEXT(b);
                            APR_BUCKET_REMOVE(b);

                            if ( !APR_BRIGADE_EMPTY(ctx->bbsave) ) {
                                APR_BRIGADE_INSERT_TAIL(ctx->bbsave, b);
                                rv = apr_brigade_pflatten(ctx->bbsave, &fbuf, &fbytes, r->pool);
                                b = apr_bucket_pool_create(fbuf, fbytes, r->pool,
                                                           r->connection->bucket_alloc);
                                apr_brigade_cleanup(ctx->bbsave);
                            }
                            APR_BRIGADE_INSERT_TAIL(bbline, b);
                            b = b1;
                        } else {
                            APR_BUCKET_REMOVE(b);
                            APR_BRIGADE_INSERT_TAIL(ctx->bbsave, b);
                            bytes = 0;
                        }
                    } /* while bytes > 0 */
				}
            } else {
                APR_BUCKET_REMOVE(b);
            }
        } else if ( APR_BUCKET_IS_EOS(b) ) {
            if ( !APR_BRIGADE_EMPTY(ctx->bbsave) ) {
                rv = apr_brigade_pflatten(ctx->bbsave, &fbuf, &fbytes, r->pool);
                b1 = apr_bucket_pool_create(fbuf, fbytes, r->pool,
                                            r->connection->bucket_alloc);
                APR_BRIGADE_INSERT_TAIL(bbline, b1);
            }
            apr_brigade_cleanup(ctx->bbsave);
            f->ctx = NULL;
            APR_BUCKET_REMOVE(b);
            APR_BRIGADE_INSERT_TAIL(bbline, b);
        } else {
            apr_bucket_delete(b);
        }
        b = APR_BRIGADE_FIRST(bb);
    }

    // 改行毎なbucketをまわす
    for ( b = APR_BRIGADE_FIRST(bbline);
          b != APR_BRIGADE_SENTINEL(bbline);
          b = APR_BUCKET_NEXT(b) ) {
        if ( !APR_BUCKET_IS_METADATA(b)
             && (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) == APR_SUCCESS)) {

            bufp = buf;

			if (ap_regexec(regex_tag_exists, bufp, 0, NULL, 0) == 0) {
				break;
			}
			
            subs = apr_strmatch(pattern_body_end_tag, bufp, bytes);
            if (subs != NULL) {
                match = ((unsigned int)subs - (unsigned int)bufp) / sizeof(char);
                bytes -= match;
                bufp += match;
                apr_bucket_split(b, match);
                b1 = APR_BUCKET_NEXT(b);
                apr_bucket_split(b1, body_end_tag_length);
                b = APR_BUCKET_NEXT(b1);
                apr_bucket_delete(b1);
                bytes -= body_end_tag_length;
                bufp += body_end_tag_length;
                b1 = apr_bucket_immortal_create(c->replace, strlen(c->replace),
                                                r->connection->bucket_alloc);
                APR_BUCKET_INSERT_BEFORE(b, b1);
            }
        }
    }
    rv = ap_pass_brigade(f->next, bbline);

    for ( b = APR_BRIGADE_FIRST(ctx->bbsave);
          b != APR_BRIGADE_SENTINEL(ctx->bbsave);
          b = APR_BUCKET_NEXT(b)) {
        apr_bucket_setaside(b, r->pool);
    }

    return rv;
}
Ejemplo n.º 23
0
static int filter_lookup(ap_filter_t *f, ap_filter_rec_t *filter)
{
    ap_filter_provider_t *provider;
    const char *str = NULL;
    char *str1;
    int match;
    unsigned int proto_flags;
    request_rec *r = f->r;
    harness_ctx *ctx = f->ctx;
    provider_ctx *pctx;
    mod_filter_ctx *rctx = ap_get_module_config(r->request_config,
                                                &filter_module);

    /* Check registered providers in order */
    for (provider = filter->providers; provider; provider = provider->next) {
        match = 1;
        switch (provider->dispatch) {
        case REQUEST_HEADERS:
            str = apr_table_get(r->headers_in, provider->value);
            break;
        case RESPONSE_HEADERS:
            str = apr_table_get(r->headers_out, provider->value);
            break;
        case SUBPROCESS_ENV:
            str = apr_table_get(r->subprocess_env, provider->value);
            break;
        case CONTENT_TYPE:
            str = r->content_type;
            break;
        case HANDLER:
            str = r->handler;
            break;
        }

        /* treat nulls so we don't have to check every strcmp individually
         * Not sure if there's anything better to do with them
         */
        if (!str) {
            if (provider->match_type == DEFINED && provider->match.string) {
                match = 0;
            }
        }
        else if (!provider->match.string) {
            match = 0;
        }
        else {
            /* Now we have no nulls, so we can do string and regexp matching */
            switch (provider->match_type) {
            case STRING_MATCH:
                if (strcasecmp(str, provider->match.string)) {
                    match = 0;
                }
                break;
            case STRING_CONTAINS:
                str1 = apr_pstrdup(r->pool, str);
                ap_str_tolower(str1);
                if (!strstr(str1, provider->match.string)) {
                    match = 0;
                }
                break;
            case REGEX_MATCH:
                if (ap_regexec(provider->match.regex, str, 0, NULL, 0)
                    == AP_REG_NOMATCH) {
                match = 0;
                }
                break;
            case INT_EQ:
                if (atoi(str) != provider->match.number) {
                    match = 0;
                }
                break;
            case INT_LT:
                if (atoi(str) < provider->match.number) {
                    match = 0;
                }
                break;
            case INT_LE:
                if (atoi(str) <= provider->match.number) {
                    match = 0;
                }
                break;
            case INT_GT:
                if (atoi(str) > provider->match.number) {
                    match = 0;
                }
                break;
            case INT_GE:
                if (atoi(str) >= provider->match.number) {
                    match = 0;
                }
                break;
            case DEFINED:        /* we already handled this:-) */
                break;
            }
        }

        if (match != provider->not) {
            /* condition matches this provider */
#ifndef NO_PROTOCOL
            /* check protocol
             *
             * FIXME:
             * This is a quick hack and almost certainly buggy.
             * The idea is that by putting this in mod_filter, we relieve
             * filter implementations of the burden of fixing up HTTP headers
             * for cases that are routinely affected by filters.
             *
             * Default is ALWAYS to do nothing, so as not to tread on the
             * toes of filters which want to do it themselves.
             *
             */
            proto_flags = provider->frec->proto_flags;

            /* some specific things can't happen in a proxy */
            if (r->proxyreq) {
                if (proto_flags & AP_FILTER_PROTO_NO_PROXY) {
                    /* can't use this provider; try next */
                    continue;
                }

                if (proto_flags & AP_FILTER_PROTO_TRANSFORM) {
                    str = apr_table_get(r->headers_out, "Cache-Control");
                    if (str) {
                        str1 = apr_pstrdup(r->pool, str);
                        ap_str_tolower(str1);
                        if (strstr(str1, "no-transform")) {
                            /* can't use this provider; try next */
                            continue;
                        }
                    }
                    apr_table_addn(r->headers_out, "Warning",
                                   apr_psprintf(r->pool,
                                                "214 %s Transformation applied",
                                                r->hostname));
                }
            }

            /* things that are invalidated if the filter transforms content */
            if (proto_flags & AP_FILTER_PROTO_CHANGE) {
                apr_table_unset(r->headers_out, "Content-MD5");
                apr_table_unset(r->headers_out, "ETag");
                if (proto_flags & AP_FILTER_PROTO_CHANGE_LENGTH) {
                    apr_table_unset(r->headers_out, "Content-Length");
                }
            }

            /* no-cache is for a filter that has different effect per-hit */
            if (proto_flags & AP_FILTER_PROTO_NO_CACHE) {
                apr_table_unset(r->headers_out, "Last-Modified");
                apr_table_addn(r->headers_out, "Cache-Control", "no-cache");
            }

            if (proto_flags & AP_FILTER_PROTO_NO_BYTERANGE) {
                apr_table_unset(r->headers_out, "Accept-Ranges");
            }
            else if (rctx && rctx->range) {
                /* restore range header we saved earlier */
                apr_table_setn(r->headers_in, "Range", rctx->range);
                rctx->range = NULL;
            }
#endif
            for (pctx = ctx->init_ctx; pctx; pctx = pctx->next) {
                if (pctx->provider == provider) {
                    ctx->fctx = pctx->ctx ;
                }
            }
            ctx->func = provider->frec->filter_func.out_func;
            return 1;
        }
    }

    /* No provider matched */
    return 0;
}
Ejemplo n.º 24
0
static int dosdetector_handler(request_rec *r)
{
	//DEBUGLOG("dosdetector_handler is called");

    dosdetector_dir_config *cfg = (dosdetector_dir_config *) ap_get_module_config(r->per_dir_config, &dosdetector_module);
	
	if(cfg->detection) return DECLINED;
    if (!ap_is_initial_req(r)) return DECLINED;

    //char **ignore_contenttype = (char **) cfg->ignore_contenttype->elts;
	
    const char *content_type;
    const char *address_tmp;
    const char *address = NULL;
    int i;

    content_type = ap_sub_req_lookup_uri(r->uri, r, NULL)->content_type;
    if (!content_type) {
#if (AP_SERVER_MINORVERSION_NUMBER > 2)
        content_type = DefaultContentType;
#else
        content_type = ap_default_type(r);
#endif
    }

	if (cfg->forwarded){
		if ((address_tmp = apr_table_get(r->headers_in, "X-Forwarded-For")) != NULL){
			const char *i = address_tmp;
			while(*i != 0 && *i != ',')
				i++;
			address = apr_pstrndup(r->pool, address_tmp, i - address_tmp);
		}
	}
	if (address == NULL) {
#if (AP_SERVER_MINORVERSION_NUMBER > 2)
		address = r->connection->client_ip;
#else
		address = r->connection->remote_ip;
#endif
    }

    ap_regmatch_t regmatch[AP_MAX_REG_MATCH];
    ap_regex_t **contenttype_regexp = (ap_regex_t **) cfg->contenttype_regexp->elts;
	for (i = 0; i < cfg->contenttype_regexp->nelts; i++) {
		if(!ap_regexec(contenttype_regexp[i], content_type, AP_MAX_REG_MATCH, regmatch, 0)){
			//ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, 0, "ignoring content-type: %s", content_type);
			return OK;
		}
    }
	DEBUGLOG("dosdetector: processing content-type: %s", content_type);

	struct in_addr addr;
	if(!cfg->forwarded) {
#if (AP_SERVER_MINORVERSION_NUMBER > 2)
		addr = r->connection->client_addr->sa.sin.sin_addr;
#else
		addr = r->connection->remote_addr->sa.sin.sin_addr;
#endif
    }
	if(cfg->forwarded || addr.s_addr == 0){
		if (inet_aton(address, &addr) == 0) {
			TRACELOG("dosdetector: '%s' is not  a valid IP addresss", address);
			return DECLINED;
		}
	}
	if (lock) apr_global_mutex_lock(lock);
	client_t *client = get_client(client_list, addr, cfg->period);
	if (lock) apr_global_mutex_unlock(lock);

	#ifdef _DEBUG
	int last_count = client->count;
	#endif
	count_increment(client, cfg->threshold);
    DEBUGLOG("dosdetector: %s, count: %d -> %d, interval: %d", address, last_count, client->count, (int)client->interval);
    //DEBUGLOG("dosdetector: %s, count: %d -> %d, interval: %d on tid %d, pid %d", address, last_count, client->count, (int)client->interval, gettid(), getpid());

	time_t now = time((time_t *)0);
	if(client->suspected > 0 && client->suspected + cfg->ban_period > now){
		apr_table_setn(r->subprocess_env, "SuspectDoS", "1");
		//apr_table_setn(r->notes, "SuspectDoS", "1");
		DEBUGLOG("dosdetector: '%s' has been still suspected as DoS attack! (suspected %d sec ago)", address, now - client->suspected);

		if(client->count > cfg->ban_threshold){
			if(client->hard_suspected == 0)
				TRACELOG("dosdetector: '%s' is suspected as Hard DoS attack! (counter: %d)", address, client->count);
			client->hard_suspected = now;
			apr_table_setn(r->subprocess_env, "SuspectHardDoS", "1");
			//apr_table_setn(r->notes, "SuspectHardDoS", "1");
		}
	} else {
        if(client->suspected > 0){
			client->suspected = 0;
			client->hard_suspected = 0;
			client->count = 0;
		}
		//int last_count = client->count;
		//client->count = client->count - client->interval * cfg->threshold;
		//if(client->count < 0)
		//	client->count = 0;
		//client->count ++;
		//DEBUGLOG("client address: %s, count: %d -> %d, interval: %d", address, last_count, client->count, client->interval);

		if(client->count > cfg->threshold){
			client->suspected = now;
			apr_table_setn(r->subprocess_env, "SuspectDoS", "1");
			//apr_table_setn(r->notes, "SuspectDoS", "1");
			TRACELOG("dosdetector: '%s' is suspected as DoS attack! (counter: %d)", address, client->count);
		}
	}

	return DECLINED;
}