diff --git a/libfreshclam/libfreshclam.c b/libfreshclam/libfreshclam.c index 04f95347a1..ede1ed2224 100644 --- a/libfreshclam/libfreshclam.c +++ b/libfreshclam/libfreshclam.c @@ -646,6 +646,22 @@ fc_error_t fc_update_database( &dbFilename, bUpdated); +#if 0 +if (FC_ERETRYLATER == ret){ + fprintf(stderr, "%s::%d::FIXME::TAKE THIS OUT\n", __FUNCTION__, __LINE__); + fprintf(stderr, "%s::%d::FIXME::TAKE THIS OUT\n", __FUNCTION__, __LINE__); + fprintf(stderr, "%s::%d::FIXME::TAKE THIS OUT\n", __FUNCTION__, __LINE__); + fprintf(stderr, "%s::%d::FIXME::TAKE THIS OUT\n", __FUNCTION__, __LINE__); + fprintf(stderr, "%s::%d::FIXME::TAKE THIS OUT\n", __FUNCTION__, __LINE__); + fprintf(stderr, "%s::%d::FIXME::TAKE THIS OUT\n", __FUNCTION__, __LINE__); + fprintf(stderr, "%s::%d::FIXME::TAKE THIS OUT\n", __FUNCTION__, __LINE__); + fprintf(stderr, "%s::%d::FIXME::TAKE THIS OUT\n", __FUNCTION__, __LINE__); + fprintf(stderr, "%s::%d::FIXME::TAKE THIS OUT\n", __FUNCTION__, __LINE__); + fprintf(stderr, "%s::%d::FIXME::TAKE THIS OUT\n", __FUNCTION__, __LINE__); + ret = FC_EFORBIDDEN; +} +#endif + switch (ret) { case FC_SUCCESS: { if (*bUpdated) { @@ -693,9 +709,19 @@ 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 (g_rayLst.cnt > 0) { + logg(LOGG_INFO, " Please provide the following cf-ray ids with your ticket.\n"); + logg(LOGG_INFO, "\n CF-RAYS=========================================================================\n"); + for (i = 0; i < g_rayLst.cnt; i++) { + logg(LOGG_INFO, " cf-ray: %s\n", g_rayLst.ids[i]); + } + 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 +821,18 @@ 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 (g_rayLst.cnt > 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 ids when\n"); + logg(LOGG_INFO, " submitting a ticket.\n"); + logg(LOGG_INFO, "\n CF-RAYS=========================================================================\n"); + for (i = 0; i < g_rayLst.cnt; i++) { + logg(LOGG_INFO, " cf-ray: %s\n", g_rayLst.ids[i]); + } + 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 +842,10 @@ 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)); + for (i = 0; i < nDatabases; i++) { if (FC_SUCCESS != (ret = fc_update_database( databaseList[i], @@ -914,7 +955,17 @@ 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 (g_rayLst.cnt > 0) { + size_t i; + logg(LOGG_INFO, " Please provide the following cf-ray ids with your ticket.\n"); + logg(LOGG_INFO, "\n CF-RAYS=========================================================================\n"); + for (i = 0; i < g_rayLst.cnt; i++) { + logg(LOGG_INFO, " cf-ray: %s\n", g_rayLst.ids[i]); + } + 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..242753a3da 100644 --- a/libfreshclam/libfreshclam.h +++ b/libfreshclam/libfreshclam.h @@ -238,6 +238,19 @@ fc_error_t fc_update_databases( void *context, uint32_t *nUpdated); +#define MAX_CFRAYS 10 +#define CFRAY_LEN 20 +typedef struct fc_cfray_list_ { + uint8_t ids[MAX_CFRAYS][CFRAY_LEN + 1]; + uint32_t cnt; +} fc_cfray_list; +#define INSERT_CFRAY(lst, ray) \ + { \ + if (lst->cnt < MAX_CFRAYS) { \ + memcpy(lst->ids[lst->cnt++], ray, CFRAY_LEN); \ + } \ + } + /* ---------------------------------------------------------------------------- * Callback function type definitions. */ diff --git a/libfreshclam/libfreshclam_internal.c b/libfreshclam/libfreshclam_internal.c index 77625b1c82..07150518ab 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; +fc_cfray_list g_rayLst = {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(fc_cfray_list) != (bread = read(handle, &g_rayLst, sizeof(fc_cfray_list)))) { + char error_message[260]; + cli_strerror(errno, error_message, 260); + logg(LOGG_ERROR, "Can't read from freshclam.dat. Bytes read: %zi, error: %s\n", bread, error_message); + goto done; + } + /* Got it. */ close(handle); handle = -1; @@ -329,6 +339,10 @@ fc_error_t save_freshclam_dat(void) logg(LOGG_DEBUG, "Saved freshclam.dat\n"); + if (-1 == write(handle, &g_rayLst, sizeof(fc_cfray_list))) { + logg(LOGG_ERROR, "Can't write to freshclam.dat\n"); + } + status = FC_SUCCESS; done: if (-1 != handle) { @@ -801,6 +815,24 @@ 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))) { + fc_cfray_list *rays = (fc_cfray_list *)userdata; + INSERT_CFRAY(rays, &(buffer[strlen(needle)])); + } + } + + return size * nitems; +} + /** * @brief Get the cvd header info struct for the newest available database. * @@ -1283,6 +1315,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_rayLst)) { + 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); @@ -1380,7 +1420,6 @@ static fc_error_t downloadFile( } done: - if (NULL != slist) { curl_slist_free_all(slist); } diff --git a/libfreshclam/libfreshclam_internal.h b/libfreshclam/libfreshclam_internal.h index 7df2b7764a..88c4e214db 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 fc_cfray_list g_rayLst; fc_error_t load_freshclam_dat(void); fc_error_t save_freshclam_dat(void);