int rate_check (struct mlfi_priv *priv, struct config_file *cfg, const char *rcpt, int is_update) { double t; struct timeval tm; int r; if (!cfg->ratelimit_enable) { return 1; } if (priv->priv_addr.family == AF_INET && is_whitelisted (&priv->priv_addr, rcpt, cfg) != 0) { msg_info("<%s>; rate_check: address is whitelisted, skipping checks", priv->mlfi_id); return 1; } tm.tv_sec = priv->conn_tm.tv_sec; tm.tv_usec = priv->conn_tm.tv_usec; t = tm.tv_sec + tm.tv_usec / 1000000.; if (is_bounce (priv->priv_from, cfg) != 0) { msg_debug( "<%s>; rate_check: bounce address detected, doing special checks: %s", priv->mlfi_id, priv->priv_from); r = check_specific_limit (priv, cfg, BOUNCE_TO, &cfg->limit_bounce_to, t, rcpt, is_update); if (r != 1) { return r; } r = check_specific_limit (priv, cfg, BOUNCE_TO_IP, &cfg->limit_bounce_to_ip, t, rcpt, is_update); if (r != 1) { return r; } } /* Check other limits */ r = check_specific_limit (priv, cfg, TO_IP_FROM, &cfg->limit_to_ip_from, t, rcpt, is_update); if (r != 1) { return r; } r = check_specific_limit (priv, cfg, TO_IP, &cfg->limit_to_ip, t, rcpt, is_update); if (r != 1) { return r; } r = check_specific_limit (priv, cfg, TO, &cfg->limit_to, t, rcpt, is_update); if (r != 1) { return r; } return 1; }
/** * Is the user a real user account? * Checks: * 1. Not root * 2. UID is above the minimum configured. * 3. Not in banned user list * Returns NULL on failure */ struct passwd* check_user(const char *user) { if (strcmp(user, "root") == 0) { fprintf(LOGFILE, "Running as root is not allowed\n"); fflush(LOGFILE); return NULL; } char *min_uid_str = get_value(MIN_USERID_KEY); int min_uid = DEFAULT_MIN_USERID; if (min_uid_str != NULL) { char *end_ptr = NULL; min_uid = strtol(min_uid_str, &end_ptr, 10); if (min_uid_str == end_ptr || *end_ptr != '\0') { fprintf(LOGFILE, "Illegal value of %s for %s in configuration\n", min_uid_str, MIN_USERID_KEY); fflush(LOGFILE); free(min_uid_str); return NULL; } free(min_uid_str); } struct passwd *user_info = get_user_info(user); if (NULL == user_info) { fprintf(LOGFILE, "User %s not found\n", user); fflush(LOGFILE); return NULL; } if (user_info->pw_uid < min_uid && !is_whitelisted(user)) { fprintf(LOGFILE, "Requested user %s is not whitelisted and has id %d," "which is below the minimum allowed %d\n", user, user_info->pw_uid, min_uid); fflush(LOGFILE); free(user_info); return NULL; } char **banned_users = get_values(BANNED_USERS_KEY); banned_users = banned_users == NULL ? (char**) DEFAULT_BANNED_USERS : banned_users; char **banned_user = banned_users; for(; *banned_user; ++banned_user) { if (strcmp(*banned_user, user) == 0) { free(user_info); if (banned_users != (char**)DEFAULT_BANNED_USERS) { free_values(banned_users); } fprintf(LOGFILE, "Requested user %s is banned\n", user); return NULL; } } if (banned_users != NULL && banned_users != (char**)DEFAULT_BANNED_USERS) { free_values(banned_users); } return user_info; }
static int access_checker(request_rec *r) { int ret = OK; /* BEGIN DoS Evasive Maneuvers Code */ if (r->prev == NULL && r->main == NULL && hit_list != NULL) { char hash_key[2048]; struct ntt_node *n; time_t t = time(NULL); /* Check whitelist */ if (is_whitelisted(r->useragent_ip)) return OK; /* First see if the IP itself is on "hold" */ n = ntt_find(hit_list, r->useragent_ip); if (n != NULL && t-n->timestamp<blocking_period) { /* If the IP is on "hold", make it wait longer in 403 land */ ret = HTTP_FORBIDDEN; n->timestamp = time(NULL); /* Not on hold, check hit stats */ } else { /* Has URI been hit too much? */ snprintf(hash_key, 2048, "%s_%s", r->useragent_ip, r->uri); n = ntt_find(hit_list, hash_key); if (n != NULL) { /* If URI is being hit too much, add to "hold" list and 403 */ if (t-n->timestamp<page_interval && n->count>=page_count) { ret = HTTP_FORBIDDEN; ntt_insert(hit_list, r->useragent_ip, time(NULL)); } else { /* Reset our hit count list as necessary */ if (t-n->timestamp>=page_interval) { n->count=0; } } n->timestamp = t; n->count++; } else { ntt_insert(hit_list, hash_key, t); } /* Has site been hit too much? */ snprintf(hash_key, 2048, "%s_SITE", r->useragent_ip); n = ntt_find(hit_list, hash_key); if (n != NULL) { /* If site is being hit too much, add to "hold" list and 403 */ if (t-n->timestamp<site_interval && n->count>=site_count) { ret = HTTP_FORBIDDEN; ntt_insert(hit_list, r->useragent_ip, time(NULL)); } else { /* Reset our hit count list as necessary */ if (t-n->timestamp>=site_interval) { n->count=0; } } n->timestamp = t; n->count++; } else { ntt_insert(hit_list, hash_key, t); } } /* Perform email notification and system functions */ if (ret == HTTP_FORBIDDEN) { char filename[1024]; struct stat s; FILE *file; snprintf(filename, sizeof(filename), "%s/dos-%s", log_dir != NULL ? log_dir : DEFAULT_LOG_DIR, r->useragent_ip); if (stat(filename, &s)) { file = fopen(filename, "w"); if (file != NULL) { fprintf(file, "%d\n", getpid()); fclose(file); LOG(LOG_ALERT, "Blacklisting address %s: possible DoS attack.", r->useragent_ip); if (email_notify != NULL) { snprintf(filename, sizeof(filename), MAILER, email_notify); file = popen(filename, "w"); if (file != NULL) { fprintf(file, "To: %s\n", email_notify); fprintf(file, "Subject: HTTP BLACKLIST %s\n\n", r->useragent_ip); fprintf(file, "mod_evasive HTTP Blacklisted %s\n", r->useragent_ip); pclose(file); } } if (system_command != NULL) { snprintf(filename, sizeof(filename), system_command, r->useragent_ip); system(filename); } } else { LOG(LOG_ALERT, "Couldn't open logfile %s: %s",filename, strerror(errno)); } } /* if (temp file does not exist) */ } /* if (ret == HTTP_FORBIDDEN) */ } /* if (r->prev == NULL && r->main == NULL && hit_list != NULL) */ /* END DoS Evasive Maneuvers Code */ if (ret == HTTP_FORBIDDEN && (ap_satisfies(r) != SATISFY_ANY || !ap_some_auth_required(r))) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "client denied by server configuration: %s", r->filename); } return ret; }
int check_access(struct ntt * ntt, const char * ip, const char * uri) { char hash_key[2048]; struct ntt_node * n; time_t t = time(NULL); int ret = OK; /* Check whitelist */ if( is_whitelisted(ntt, ip) ) { return OK; } /* First see if the IP itself is on "hold" */ n = ntt_find(ntt, ip); if( n && t - n->timestamp < blocking_period ) { /* If the IP is on "hold", make it wait longer in 403 land */ n->timestamp = time(NULL); ntt_update(ntt, ip, n->timestamp, n->count); ntt_cleanup(n); return HTTP_FORBIDDEN; } /* Not on hold, check hit stats */ /* Has URI been hit too much? */ snprintf(hash_key, 2048, "%s_%s", ip, uri); n = ntt_find(ntt, hash_key); if( n ) { /* If URI is being hit too much, add to "hold" list and 403 */ if( t - n->timestamp < page_interval && n->count >= page_count ) { ret = HTTP_FORBIDDEN; ntt_insert(ntt, ip, time(NULL)); } else { /* Reset our hit count list as necessary */ if( t - n->timestamp >= page_interval ) { n->count=0; } } n->timestamp = t; n->count++; ntt_update(ntt, hash_key, n->timestamp, n->count); ntt_cleanup(n); return ret; } // Insert ntt_insert(ntt, hash_key, t); /* Has site been hit too much? */ snprintf(hash_key, 2048, "%s_SITE", ip); n = ntt_find(ntt, hash_key); if( n ) { /* If site is being hit too much, add to "hold" list and 403 */ if( t - n->timestamp < site_interval && n->count >= site_count ) { ret = HTTP_FORBIDDEN; ntt_insert(ntt, ip, time(NULL)); } else { /* Reset our hit count list as necessary */ if (t-n->timestamp>=site_interval) { n->count=0; } } n->timestamp = t; n->count++; ntt_update(ntt, hash_key, n->timestamp, n->count); ntt_cleanup(n); return ret; } // Insert ntt_insert(ntt, hash_key, t); return ret; }