Skip to content

Commit 899ee0c

Browse files
author
Felipe Zimmerle
committed
Adds support to load remote resources to pmFromFile and ipMatchFromFile
Initially those directives were only able to load content from a local file. This commit extends this functionality allowing the user to provide an HTTP URI that can be downloaded and loaded by ModSecurity. Initially the download is associated with a server restart. For next versions we expect to load such resources as it become outdated (Without need to resetart the server).
1 parent 81bde08 commit 899ee0c

File tree

5 files changed

+352
-51
lines changed

5 files changed

+352
-51
lines changed

apache2/msc_util.c

Lines changed: 157 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
#include "msc_util.h"
2424

2525
#include <apr_lib.h>
26+
#include <apr_sha1.h>
2627
#include "modsecurity_config.h"
2728

29+
#include "curl/curl.h"
30+
2831
/**
2932
* NOTE: Be careful as these can ONLY be used on static values for X.
3033
* (i.e. VALID_HEX(c++) will NOT work)
@@ -2593,7 +2596,7 @@ int ip_tree_from_file(TreeRoot **rtree, char *uri,
25932596
tnode = TreeAddIP(start, (*rtree)->ipv6_tree, IPV6_TREE);
25942597
}
25952598
#endif
2596-
2599+
25972600
if (tnode == NULL)
25982601
{
25992602
*error_msg = apr_psprintf(mp, "Could not add entry " \
@@ -2610,6 +2613,140 @@ int ip_tree_from_file(TreeRoot **rtree, char *uri,
26102613
return 0;
26112614
}
26122615

2616+
int ip_tree_from_uri(TreeRoot **rtree, char *uri,
2617+
apr_pool_t *mp, char **error_msg)
2618+
{
2619+
TreeNode *tnode = NULL;
2620+
apr_status_t rc;
2621+
int line = 0;
2622+
apr_file_t *fd;
2623+
char *start;
2624+
char *end;
2625+
char buf[HUGE_STRING_LEN + 1]; // FIXME: 2013-10-29 zimmerle: dynamic?
2626+
char errstr[1024]; //
2627+
2628+
CURL *curl;
2629+
CURLcode res;
2630+
2631+
char id[(APR_SHA1_DIGESTSIZE*2) + 1];
2632+
char *apr_id = NULL;
2633+
char *beacon_str = NULL;
2634+
int beacon_str_len = 0;
2635+
char *beacon_apr = NULL;
2636+
struct msc_curl_memory_buffer_t chunk;
2637+
chunk.memory = malloc(1); /* will be grown as needed by the realloc above */
2638+
chunk.size = 0; /* no data at this point */
2639+
char *word = NULL;
2640+
char *brkt = NULL;
2641+
char *sep = "\n";
2642+
2643+
2644+
2645+
if (create_radix_tree(mp, rtree, error_msg))
2646+
{
2647+
return -1;
2648+
}
2649+
2650+
/* Retrieve the beacon string */
2651+
beacon_str_len = msc_beacon_string(NULL, 0);
2652+
2653+
beacon_str = malloc(sizeof(char) * beacon_str_len + 1);
2654+
if (beacon_str == NULL) {
2655+
beacon_str = "Failed to retrieve beacon string";
2656+
beacon_apr = apr_psprintf(mp, "ModSec-status: %s", beacon_str);
2657+
}
2658+
else
2659+
{
2660+
msc_beacon_string(beacon_str, beacon_str_len);
2661+
beacon_apr = apr_psprintf(mp, "ModSec-status: %s", beacon_str);
2662+
free(beacon_str);
2663+
}
2664+
2665+
memset(id, '\0', sizeof(id));
2666+
if (msc_status_engine_unique_id(id)) {
2667+
sprintf(id, "no unique id");
2668+
}
2669+
2670+
apr_id = apr_psprintf(mp, "ModSec-unique-id: %s", id);
2671+
curl_global_init(CURL_GLOBAL_ALL);
2672+
curl = curl_easy_init();
2673+
2674+
if (curl) {
2675+
struct curl_slist *headers_chunk = NULL;
2676+
curl_easy_setopt(curl, CURLOPT_URL, uri);
2677+
2678+
headers_chunk = curl_slist_append(headers_chunk, apr_id);
2679+
headers_chunk = curl_slist_append(headers_chunk, beacon_apr);
2680+
2681+
/* send all data to this function */
2682+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, msc_curl_write_memory_cb);
2683+
2684+
/* we pass our 'chunk' struct to the callback function */
2685+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
2686+
2687+
/* some servers don't like requests that are made without a user-agent
2688+
field, so we provide one */
2689+
curl_easy_setopt(curl, CURLOPT_USERAGENT, "ModSecurity");
2690+
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers_chunk);
2691+
2692+
res = curl_easy_perform(curl);
2693+
2694+
if (res != CURLE_OK)
2695+
{
2696+
*error_msg = apr_psprintf(mp, "Failed to fetch \"%s\" error: %s ", uri, curl_easy_strerror(res));
2697+
return -1;
2698+
}
2699+
2700+
curl_easy_cleanup(curl);
2701+
curl_slist_free_all(headers_chunk);
2702+
}
2703+
curl_global_cleanup();
2704+
2705+
for (word = strtok_r(chunk.memory, sep, &brkt);
2706+
word;
2707+
word = strtok_r(NULL, sep, &brkt))
2708+
{
2709+
int i = 0;
2710+
line++;
2711+
2712+
/* Ignore empty lines and comments */
2713+
if (*word == '#') continue;
2714+
2715+
for (i = 0; i < strlen(word); i++)
2716+
{
2717+
if (apr_isxdigit(word[i]) || word[i] == '.' || word[i] == '/' || word[i] == ':' || word[i] == '\n')
2718+
{
2719+
continue;
2720+
}
2721+
2722+
*error_msg = apr_psprintf(mp, "Invalid char \"%c\" in line %d " \
2723+
"of uri %s", *end, line, uri);
2724+
return -1;
2725+
}
2726+
2727+
if (strchr(word, ':') == NULL)
2728+
{
2729+
tnode = TreeAddIP(word, (*rtree)->ipv4_tree, IPV4_TREE);
2730+
}
2731+
#if APR_HAVE_IPV6
2732+
else
2733+
{
2734+
tnode = TreeAddIP(word, (*rtree)->ipv6_tree, IPV6_TREE);
2735+
}
2736+
#endif
2737+
2738+
if (tnode == NULL)
2739+
{
2740+
*error_msg = apr_psprintf(mp, "Could not add entry " \
2741+
"\"%s\" in line %d of file %s to IP list", word, line, uri);
2742+
return -1;
2743+
}
2744+
2745+
}
2746+
return 0;
2747+
}
2748+
2749+
26132750
int tree_contains_ip(apr_pool_t *mp, TreeRoot *rtree,
26142751
const char *value, modsec_rec *msr, char **error_msg)
26152752
{
@@ -2691,3 +2828,22 @@ int ip_tree_from_param(apr_pool_t *mp,
26912828
return 0;
26922829
}
26932830

2831+
size_t msc_curl_write_memory_cb(void *contents, size_t size,
2832+
size_t nmemb, void *userp)
2833+
{
2834+
size_t realsize = size * nmemb;
2835+
struct msc_curl_memory_buffer_t *mem = (struct msc_curl_memory_buffer_t *)userp;
2836+
2837+
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
2838+
if(mem->memory == NULL) {
2839+
/* out of memory! */
2840+
return 0;
2841+
}
2842+
2843+
memcpy(&(mem->memory[mem->size]), contents, realsize);
2844+
mem->size += realsize;
2845+
mem->memory[mem->size] = 0;
2846+
2847+
return realsize;
2848+
}
2849+

apache2/msc_util.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,13 @@ int DSOLOCAL ip_tree_from_param(apr_pool_t *pool,
161161

162162
int read_line(char *buff, int size, FILE *fp);
163163

164+
size_t msc_curl_write_memory_cb(void *contents, size_t size,
165+
size_t nmemb, void *userp);
166+
167+
struct msc_curl_memory_buffer_t
168+
{
169+
char *memory;
170+
size_t size;
171+
};
172+
164173
#endif

0 commit comments

Comments
 (0)