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,
25932596tnode = TreeAddIP (start , (* rtree )-> ipv6_tree ,IPV6_TREE );
25942597 }
25952598#endif
2596-
2599+
25972600if (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,
26102613return 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+
26132750int tree_contains_ip (apr_pool_t * mp ,TreeRoot * rtree ,
26142751const char * value ,modsec_rec * msr ,char * * error_msg )
26152752{
@@ -2691,3 +2828,22 @@ int ip_tree_from_param(apr_pool_t *mp,
26912828return 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+