diff --git a/libfreshclam/libfreshclam.c b/libfreshclam/libfreshclam.c index 04f95347a1..304d35a638 100644 --- a/libfreshclam/libfreshclam.c +++ b/libfreshclam/libfreshclam.c @@ -693,9 +693,17 @@ fc_error_t fc_update_database( logg(LOGG_INFO, " In order to rectify this please check that you are:\n"); logg(LOGG_INFO, " a. Running an up-to-date version of FreshClam\n"); logg(LOGG_INFO, " b. Running FreshClam no more than once an hour\n"); - logg(LOGG_INFO, " c. If you have checked (a) and (b), please open a ticket at\n"); + logg(LOGG_INFO, " c. Connecting from an IP in a blocked region\n"); + logg(LOGG_INFO, " Please see https://www.cisco.com/c/m/en_us/crisissupport.html\n"); + logg(LOGG_INFO, " d. If you have checked (a), (b) and (c), please open a ticket at\n"); logg(LOGG_INFO, " https://github.com/Cisco-Talos/clamav/issues\n"); logg(LOGG_INFO, " and we will investigate why your network is blocked.\n"); + if (0 != g_lastRay[0]) { + logg(LOGG_INFO, " Please provide the following cf-ray id with your ticket.\n"); + logg(LOGG_INFO, "\n CF-RAY=========================================================================\n"); + logg(LOGG_INFO, " cf-ray: %s\n", g_lastRay); + logg(LOGG_INFO, "\n"); + } logg(LOGG_WARNING, "You are on cool-down until after: %s\n", retry_after_string); status = ret; goto done; @@ -795,7 +803,16 @@ fc_error_t fc_update_databases( logg(LOGG_INFO, " CDN and your own network.\n"); logg(LOGG_INFO, " 4. Please do not open a ticket asking for an exemption from the rate limit,\n"); logg(LOGG_INFO, " it will not be granted.\n"); + if (0 != g_lastRay[0]) { + logg(LOGG_INFO, " 5. If you have verified that you are not blocked due to your region, and have\n"); + logg(LOGG_INFO, " not exceeded the rate limit, please provide the following cf-ray id when\n"); + logg(LOGG_INFO, " submitting a ticket.\n"); + logg(LOGG_INFO, "\n CF-RAY=========================================================================\n"); + logg(LOGG_INFO, " cf-ray: %s\n", g_lastRay); + logg(LOGG_INFO, "\n"); + } logg(LOGG_WARNING, "You are still on cool-down until after: %s\n", retry_after_string); + status = FC_SUCCESS; goto done; } else { @@ -805,6 +822,11 @@ fc_error_t fc_update_databases( } } + /*Clear the old cf-ray ids. This is really only so that + * we don't have stale ones when we are running in daemon mode.*/ + //memset(&g_rayLst, 0, sizeof(g_rayLst)); + memset(&g_lastRay, 0, sizeof(g_lastRay)); + for (i = 0; i < nDatabases; i++) { if (FC_SUCCESS != (ret = fc_update_database( databaseList[i], @@ -914,7 +936,15 @@ fc_error_t fc_download_url_database( logg(LOGG_INFO, " c. If you have checked (a) and (b), please open a ticket at\n"); logg(LOGG_INFO, " https://github.com/Cisco-Talos/clamav/issues\n"); logg(LOGG_INFO, " and we will investigate why your network is blocked.\n"); + if (0 != g_lastRay[0]) { + size_t i; + logg(LOGG_INFO, " Please provide the following cf-ray id with your ticket.\n"); + logg(LOGG_INFO, "\n CF-RAY=========================================================================\n"); + logg(LOGG_INFO, " cf-ray: %s\n", g_lastRay); + logg(LOGG_INFO, "\n"); + } logg(LOGG_WARNING, "You are on cool-down until after: %s\n", retry_after_string); + status = ret; goto done; break; diff --git a/libfreshclam/libfreshclam.h b/libfreshclam/libfreshclam.h index 25d7293fef..bda51d2755 100644 --- a/libfreshclam/libfreshclam.h +++ b/libfreshclam/libfreshclam.h @@ -238,6 +238,9 @@ fc_error_t fc_update_databases( void *context, uint32_t *nUpdated); +/*Length of a cf-ray id.*/ +#define CFRAY_LEN 20 + /* ---------------------------------------------------------------------------- * Callback function type definitions. */ diff --git a/libfreshclam/libfreshclam_internal.c b/libfreshclam/libfreshclam_internal.c index 77625b1c82..806cb8f9ca 100644 --- a/libfreshclam/libfreshclam_internal.c +++ b/libfreshclam/libfreshclam_internal.c @@ -118,6 +118,8 @@ uint32_t g_bCompressLocalDatabase = 0; freshclam_dat_v1_t *g_freshclamDat = NULL; +uint8_t g_lastRay[CFRAY_LEN+1] = {0}; + /** @brief Generate a Version 4 UUID according to RFC-4122 * * Uses the openssl RAND_bytes function to generate a Version 4 UUID. @@ -217,8 +219,9 @@ fc_error_t load_freshclam_dat(void) /* Verify that file size is as expected. */ off_t file_size = lseek(handle, 0L, SEEK_END); - if (strlen(MIRRORS_DAT_MAGIC) + sizeof(freshclam_dat_v1_t) != (size_t)file_size) { - logg(LOGG_DEBUG, "freshclam.dat is bigger than expected: %zu != %ld\n", sizeof(freshclam_dat_v1_t), file_size); + size_t minSize = strlen(MIRRORS_DAT_MAGIC) + sizeof(freshclam_dat_v1_t); + if (minSize > (size_t)file_size) { + logg(LOGG_DEBUG, "freshclam.dat is smaller than expected: %zu != %ld\n", sizeof(freshclam_dat_v1_t), file_size); goto done; } @@ -244,6 +247,13 @@ fc_error_t load_freshclam_dat(void) goto done; } + if (sizeof(g_lastRay) != (bread = read(handle, &g_lastRay, sizeof(g_lastRay)))) { + char error_message[260]; + cli_strerror(errno, error_message, 260); + logg(LOGG_WARNING, "Last cf-ray not present in freshclam.dat.\n"); + memset(g_lastRay, 0, sizeof(g_lastRay)); + } + /* Got it. */ close(handle); handle = -1; @@ -327,6 +337,10 @@ fc_error_t save_freshclam_dat(void) logg(LOGG_ERROR, "Can't write to freshclam.dat\n"); } + if (-1 == write(handle, &g_lastRay, sizeof(g_lastRay))) { + logg(LOGG_ERROR, "Can't write to freshclam.dat\n"); + } + logg(LOGG_DEBUG, "Saved freshclam.dat\n"); status = FC_SUCCESS; @@ -801,6 +815,25 @@ static size_t WriteFileCallback(void *contents, size_t size, size_t nmemb, void return bytes_written; } +size_t HeaderCallback(char *buffer, + size_t size, + size_t nitems, + void *userdata) +{ + + const char *const needle = "cf-ray: "; + size_t totBytes = size * nitems; + if (totBytes >= strlen(needle) + CFRAY_LEN) { + if (0 == strncmp(needle, buffer, strlen(needle))) { + uint8_t ** last = (uint8_t**) userdata; + memcpy(last, &(buffer[strlen(needle)]), CFRAY_LEN); + last[CFRAY_LEN] = 0; + } + } + + return size * nitems; +} + /** * @brief Get the cvd header info struct for the newest available database. * @@ -1283,6 +1316,14 @@ static fc_error_t downloadFile( logg(LOGG_ERROR, "downloadFile: Failed to set write-data file handle for curl session.\n"); } + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HEADERDATA, &g_lastRay)) { + logg(LOGG_ERROR, "downloadFile: Failed to set header-data for header callback for curl session.\n"); + } + + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, HeaderCallback)) { + logg(LOGG_ERROR, "downloadFile: Failed to set header-data callback function for curl session.\n"); + } + logg(LOGG_DEBUG, "downloadFile: Download source: %s\n", url); logg(LOGG_DEBUG, "downloadFile: Download destination: %s\n", destfile); diff --git a/libfreshclam/libfreshclam_internal.h b/libfreshclam/libfreshclam_internal.h index 7df2b7764a..7651af7aa4 100644 --- a/libfreshclam/libfreshclam_internal.h +++ b/libfreshclam/libfreshclam_internal.h @@ -64,6 +64,7 @@ extern uint32_t g_requestTimeout; extern uint32_t g_bCompressLocalDatabase; extern freshclam_dat_v1_t *g_freshclamDat; +extern uint8_t g_lastRay[CFRAY_LEN+1]; fc_error_t load_freshclam_dat(void); fc_error_t save_freshclam_dat(void);