Cloudflare deprecated the __cfduid cookie which caused ClamSubmit
failures on systems that stopped receiving the cookie.
This commit removes support for the __cfduid cookie.
Also made the session cookie optional, in case that disappears too.
Changed error messages over to use the logg() function like our other apps.
Tidied up some of the logic, and changed "cleanup" label to "done" to
match other code.
... | ... |
@@ -1,3 +1,30 @@ |
1 |
+/* |
|
2 |
+ * ClamAV Malware and False Positive Reporting Tool |
|
3 |
+ * |
|
4 |
+ * Copyright (C) 2014-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved. |
|
5 |
+ * |
|
6 |
+ * Authors: Shawn Webb, Steve Morgan |
|
7 |
+ * |
|
8 |
+ * This program is free software; you can redistribute it and/or modify |
|
9 |
+ * it under the terms of the GNU General Public License version 2 as |
|
10 |
+ * published by the Free Software Foundation. |
|
11 |
+ * |
|
12 |
+ * This program is distributed in the hope that it will be useful, |
|
13 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
15 |
+ * GNU General Public License for more details. |
|
16 |
+ * |
|
17 |
+ * You should have received a copy of the GNU General Public License |
|
18 |
+ * along with this program; if not, write to the Free Software |
|
19 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
20 |
+ * MA 02110-1301, USA. |
|
21 |
+ */ |
|
22 |
+ |
|
23 |
+#ifdef HAVE_CONFIG_H |
|
24 |
+#include "clamav-config.h" |
|
25 |
+#endif |
|
26 |
+ |
|
27 |
+#include <stdbool.h> |
|
1 | 28 |
#include <stdio.h> |
2 | 29 |
#include <stdlib.h> |
3 | 30 |
#if HAVE_UNISTD_H |
... | ... |
@@ -23,6 +50,7 @@ |
23 | 23 |
#include "misc.h" |
24 | 24 |
#include "getopt.h" |
25 | 25 |
#include "cert_util.h" |
26 |
+#include "output.h" |
|
26 | 27 |
|
27 | 28 |
#define OPTS "e:p:n:N:V:H:h?v?d" |
28 | 29 |
|
... | ... |
@@ -32,7 +60,6 @@ void version(void); |
32 | 32 |
|
33 | 33 |
typedef struct _header_data { |
34 | 34 |
int len; |
35 |
- char *cfduid; |
|
36 | 35 |
char *session; |
37 | 36 |
} header_data; |
38 | 37 |
|
... | ... |
@@ -41,7 +68,7 @@ typedef struct _write_data { |
41 | 41 |
char *str; |
42 | 42 |
} write_data; |
43 | 43 |
|
44 |
-int g_debug = 0; |
|
44 |
+bool g_debug = false; |
|
45 | 45 |
|
46 | 46 |
void usage(char *name) |
47 | 47 |
{ |
... | ... |
@@ -85,22 +112,22 @@ size_t header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) |
85 | 85 |
sp = ptr + clen + 1; |
86 | 86 |
ep = strchr(sp, ';'); |
87 | 87 |
if (ep == NULL) { |
88 |
- fprintf(stderr, "header_cb(): malformed cookie\n"); |
|
88 |
+ logg("!header_cb(): malformed cookie\n"); |
|
89 | 89 |
return 0; |
90 | 90 |
} |
91 | 91 |
mem = malloc(ep - sp + 1); |
92 | 92 |
if (mem == NULL) { |
93 |
- fprintf(stderr, "header_cb(): malloc failed\n"); |
|
93 |
+ logg("!header_cb(): malloc failed\n"); |
|
94 | 94 |
return 0; |
95 | 95 |
} |
96 | 96 |
memcpy(mem, sp, ep - sp); |
97 | 97 |
mem[ep - sp] = '\0'; |
98 |
- if (!strncmp(mem, "__cfduid", 8)) |
|
99 |
- hd->cfduid = mem; |
|
100 |
- else if (!strncmp(mem, "_clamav-net_session", strlen("_clamav-net_session"))) |
|
98 |
+ if (!strncmp(mem, "_clamav-net_session", strlen("_clamav-net_session"))) |
|
101 | 99 |
hd->session = mem; |
102 |
- else |
|
103 |
- fprintf(stderr, "header_cb(): unrecognized cookie\n"); |
|
100 |
+ else { |
|
101 |
+ logg("!header_cb(): unrecognized cookie\n"); |
|
102 |
+ free(mem); |
|
103 |
+ } |
|
104 | 104 |
} |
105 | 105 |
return len; |
106 | 106 |
} |
... | ... |
@@ -114,7 +141,7 @@ size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) |
114 | 114 |
if (len) { |
115 | 115 |
str = realloc(wd->str, wd->len + len + 1); |
116 | 116 |
if (str == NULL) { |
117 |
- fprintf(stderr, "write_cb() realloc failure\n"); |
|
117 |
+ logg("!write_cb() realloc failure\n"); |
|
118 | 118 |
return 0; |
119 | 119 |
} |
120 | 120 |
memcpy(str + wd->len, ptr, len); |
... | ... |
@@ -140,10 +167,10 @@ const char *presigned_get_string(json_object *ps_json_obj, char *key) |
140 | 140 |
if (json_object_object_get_ex(ps_json_obj, key, &json_obj)) { |
141 | 141 |
json_str = json_object_get_string(json_obj); |
142 | 142 |
if (json_str == NULL) { |
143 |
- fprintf(stderr, "Error: json_object_get_string() for %s.\n", key); |
|
143 |
+ logg("!Error: json_object_get_string() for %s.\n", key); |
|
144 | 144 |
} |
145 | 145 |
} else { |
146 |
- fprintf(stderr, "Error: json_object_object_get_ex() for %s.\n", key); |
|
146 |
+ logg("!Error: json_object_object_get_ex() for %s.\n", key); |
|
147 | 147 |
} |
148 | 148 |
return json_str; |
149 | 149 |
} |
... | ... |
@@ -161,23 +188,28 @@ int main(int argc, char *argv[]) |
161 | 161 |
int setURL = 0, fromStream = 0; |
162 | 162 |
const char *json_str; |
163 | 163 |
write_data wd = {0, NULL}; |
164 |
- header_data hd_malware = {0, NULL, NULL}; |
|
165 |
- header_data hd_presigned = {0, NULL, NULL}; |
|
164 |
+ header_data hd_malware = {0, NULL}; |
|
165 |
+ header_data hd_presigned = {0, NULL}; |
|
166 | 166 |
json_object *ps_json_obj = NULL; |
167 |
- int malware = 0; |
|
167 |
+ bool malware = false; |
|
168 | 168 |
int len = 0; |
169 | 169 |
char *submissionID = NULL; |
170 | 170 |
char *fpvname = NULL; |
171 |
- char *sp, *ep, *str; |
|
172 |
- char *authenticity_token = NULL; |
|
173 |
- char *urlp; |
|
171 |
+ char *sp, *ep; |
|
172 |
+ |
|
173 |
+ char *authenticity_token_header = NULL; |
|
174 |
+ char *authenticity_token = NULL; |
|
175 |
+ char *session_cookie = NULL; |
|
176 |
+ |
|
177 |
+ char *url_for_auth_token; |
|
178 |
+ char *url_for_presigned_cookie; |
|
174 | 179 |
|
175 | 180 |
curl_global_init(CURL_GLOBAL_ALL); |
176 | 181 |
|
177 | 182 |
clam_curl = curl_easy_init(); |
178 | 183 |
if (clam_curl == NULL) { |
179 |
- fprintf(stderr, "ERROR: Could not initialize libcurl.\n"); |
|
180 |
- goto cleanup; |
|
184 |
+ logg("!ERROR: Could not initialize libcurl.\n"); |
|
185 |
+ goto done; |
|
181 | 186 |
} |
182 | 187 |
|
183 | 188 |
memset(userAgent, 0, sizeof(userAgent)); |
... | ... |
@@ -187,7 +219,7 @@ int main(int argc, char *argv[]) |
187 | 187 |
userAgent[sizeof(userAgent) - 1] = 0; |
188 | 188 |
|
189 | 189 |
if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_USERAGENT, userAgent)) { |
190 |
- fprintf(stderr, "!create_curl_handle: Failed to set CURLOPT_USERAGENT (%s)!\n", userAgent); |
|
190 |
+ logg("!!create_curl_handle: Failed to set CURLOPT_USERAGENT (%s)!\n", userAgent); |
|
191 | 191 |
} |
192 | 192 |
|
193 | 193 |
while ((ch = my_getopt(argc, argv, OPTS)) > 0) { |
... | ... |
@@ -209,14 +241,14 @@ int main(int argc, char *argv[]) |
209 | 209 |
case 'n': |
210 | 210 |
if (setURL) |
211 | 211 |
usage(argv[0]); |
212 |
- malware = 1; |
|
212 |
+ malware = true; |
|
213 | 213 |
filename = optarg; |
214 | 214 |
break; |
215 | 215 |
case 'V': |
216 | 216 |
fpvname = optarg; |
217 | 217 |
break; |
218 | 218 |
case 'd': |
219 |
- g_debug = 1; |
|
219 |
+ g_debug = true; |
|
220 | 220 |
break; |
221 | 221 |
case 'h': |
222 | 222 |
case '?': |
... | ... |
@@ -228,15 +260,15 @@ int main(int argc, char *argv[]) |
228 | 228 |
if (!(name) || !(email) || !(filename)) |
229 | 229 |
usage(argv[0]); |
230 | 230 |
|
231 |
- if (malware == 0 && fpvname == NULL) { |
|
232 |
- fprintf(stderr, "Detected virus name(-V) required for false positive submissions.\n"); |
|
231 |
+ if (malware == false && fpvname == NULL) { |
|
232 |
+ logg("!Detected virus name(-V) required for false positive submissions.\n"); |
|
233 | 233 |
usage(argv[0]); |
234 | 234 |
} |
235 | 235 |
if (strlen(filename) == 1 && filename[0] == '-') { |
236 | 236 |
filename = read_stream(); |
237 | 237 |
if (!(filename)) { |
238 |
- fprintf(stderr, "ERROR: Unable to read stream\n"); |
|
239 |
- goto cleanup; |
|
238 |
+ logg("!ERROR: Unable to read stream\n"); |
|
239 |
+ goto done; |
|
240 | 240 |
} |
241 | 241 |
fromStream = 1; |
242 | 242 |
} |
... | ... |
@@ -244,31 +276,34 @@ int main(int argc, char *argv[]) |
244 | 244 |
if (g_debug) { |
245 | 245 |
/* ask libcurl to show us the verbose output */ |
246 | 246 |
if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_VERBOSE, 1L)) { |
247 |
- fprintf(stderr, "!ERROR: Failed to set CURLOPT_VERBOSE!\n"); |
|
247 |
+ logg("!!ERROR: Failed to set CURLOPT_VERBOSE!\n"); |
|
248 | 248 |
} |
249 | 249 |
if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_STDERR, stdout)) { |
250 |
- fprintf(stderr, "!ERROR: Failed to direct curl debug output to stdout!\n"); |
|
250 |
+ logg("!!ERROR: Failed to direct curl debug output to stdout!\n"); |
|
251 | 251 |
} |
252 | 252 |
} |
253 | 253 |
|
254 | 254 |
if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1)) { |
255 |
- fprintf(stderr, "ERROR: Failed to set HTTP version to 1.1 (to prevent 2.0 responses which we don't yet parse properly)!\n"); |
|
255 |
+ logg("!ERROR: Failed to set HTTP version to 1.1 (to prevent 2.0 responses which we don't yet parse properly)!\n"); |
|
256 | 256 |
} |
257 | 257 |
|
258 | 258 |
#if defined(C_DARWIN) || defined(_WIN32) |
259 | 259 |
if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function)) { |
260 |
- fprintf(stderr, "ERROR: Failed to set SSL CTX function!\n"); |
|
260 |
+ logg("!ERROR: Failed to set SSL CTX function!\n"); |
|
261 | 261 |
} |
262 | 262 |
#else |
263 | 263 |
set_tls_ca_bundle(clam_curl); |
264 | 264 |
#endif |
265 | 265 |
|
266 |
- /*** The GET malware|fp ***/ |
|
267 |
- if (malware == 1) |
|
268 |
- urlp = "https://www.clamav.net/reports/malware"; |
|
269 |
- else |
|
270 |
- urlp = "https://www.clamav.net/reports/fp"; |
|
271 |
- curl_easy_setopt(clam_curl, CURLOPT_URL, urlp); |
|
266 |
+ /* |
|
267 |
+ * GET authenticity token |
|
268 |
+ */ |
|
269 |
+ if (malware == true) { |
|
270 |
+ url_for_auth_token = "https://www.clamav.net/reports/malware"; |
|
271 |
+ } else { |
|
272 |
+ url_for_auth_token = "https://www.clamav.net/reports/fp"; |
|
273 |
+ } |
|
274 |
+ curl_easy_setopt(clam_curl, CURLOPT_URL, url_for_auth_token); |
|
272 | 275 |
curl_easy_setopt(clam_curl, CURLOPT_HTTPGET, 1); |
273 | 276 |
curl_easy_setopt(clam_curl, CURLOPT_WRITEDATA, &wd); |
274 | 277 |
curl_easy_setopt(clam_curl, CURLOPT_WRITEFUNCTION, write_cb); |
... | ... |
@@ -276,30 +311,30 @@ int main(int argc, char *argv[]) |
276 | 276 |
curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, header_cb); |
277 | 277 |
res = curl_easy_perform(clam_curl); |
278 | 278 |
if (res != CURLE_OK) { |
279 |
- fprintf(stderr, "Error in GET %s: %s\n", urlp, curl_easy_strerror(res)); |
|
280 |
- goto cleanup; |
|
279 |
+ logg("!Error in GET %s: %s\n", url_for_auth_token, curl_easy_strerror(res)); |
|
280 |
+ goto done; |
|
281 | 281 |
} |
282 | 282 |
if (wd.str != NULL) { |
283 | 283 |
sp = strstr(wd.str, "name=\"authenticity_token\""); |
284 | 284 |
if (sp == NULL) { |
285 |
- fprintf(stderr, "Authenticity token element not found.\n"); |
|
286 |
- goto cleanup; |
|
285 |
+ logg("!Authenticity token element not found.\n"); |
|
286 |
+ goto done; |
|
287 | 287 |
} |
288 | 288 |
sp = strstr(sp, "value="); |
289 | 289 |
if (sp == NULL) { |
290 |
- fprintf(stderr, "Authenticity token value not found.\n"); |
|
291 |
- goto cleanup; |
|
290 |
+ logg("!Authenticity token value not found.\n"); |
|
291 |
+ goto done; |
|
292 | 292 |
} |
293 | 293 |
sp += 7; |
294 | 294 |
ep = strchr(sp, '"'); |
295 | 295 |
if (ep == NULL) { |
296 |
- fprintf(stderr, "Authenticity token malformed.\n"); |
|
297 |
- goto cleanup; |
|
296 |
+ logg("!Authenticity token malformed.\n"); |
|
297 |
+ goto done; |
|
298 | 298 |
} |
299 | 299 |
authenticity_token = malloc(ep - sp + 1); |
300 | 300 |
if (authenticity_token == NULL) { |
301 |
- fprintf(stderr, "no memory for authenticity token.\n"); |
|
302 |
- goto cleanup; |
|
301 |
+ logg("!no memory for authenticity token.\n"); |
|
302 |
+ goto done; |
|
303 | 303 |
} |
304 | 304 |
memcpy(authenticity_token, sp, ep - sp); |
305 | 305 |
authenticity_token[ep - sp] = '\0'; |
... | ... |
@@ -307,120 +342,128 @@ int main(int argc, char *argv[]) |
307 | 307 |
wd.str = NULL; |
308 | 308 |
} |
309 | 309 |
wd.len = 0; |
310 |
- urlp = NULL; |
|
311 | 310 |
|
312 |
- /*** The GET presigned ***/ |
|
313 |
- if (malware == 1) |
|
314 |
- curl_easy_setopt(clam_curl, CURLOPT_URL, "https://www.clamav.net/presigned?type=malware"); |
|
315 |
- else |
|
316 |
- curl_easy_setopt(clam_curl, CURLOPT_URL, "https://www.clamav.net/presigned?type=fp"); |
|
311 |
+ /* record the session cookie for later use, if exists */ |
|
312 |
+ if (NULL == hd_malware.session) { |
|
313 |
+ logg("!clamav.net/presigned response missing session ID cookie.\nWill try without the cookie.\n"); |
|
314 |
+ // goto done; // Note: unclear if the session cookie is required. Can't hurt to try w/out it? |
|
315 |
+ } else { |
|
316 |
+ len = strlen(hd_malware.session) + 3; |
|
317 |
+ session_cookie = malloc(len); |
|
318 |
+ if (session_cookie == NULL) { |
|
319 |
+ logg("!No memory for GET presigned cookies\n"); |
|
320 |
+ goto done; |
|
321 |
+ } |
|
322 |
+ if (snprintf(session_cookie, len, "%s;", hd_malware.session) > len) { |
|
323 |
+ logg("!snprintf() failed formatting GET presigned cookies\n"); |
|
324 |
+ goto done; |
|
325 |
+ } |
|
326 |
+ } |
|
327 |
+ |
|
328 |
+ /* |
|
329 |
+ * GET presigned cookie |
|
330 |
+ */ |
|
331 |
+ if (malware == true) { |
|
332 |
+ url_for_presigned_cookie = "https://www.clamav.net/presigned?type=malware"; |
|
333 |
+ } else { |
|
334 |
+ url_for_presigned_cookie = "https://www.clamav.net/presigned?type=fp"; |
|
335 |
+ } |
|
336 |
+ |
|
337 |
+ curl_easy_setopt(clam_curl, CURLOPT_URL, url_for_presigned_cookie); |
|
317 | 338 |
curl_easy_setopt(clam_curl, CURLOPT_HTTPGET, 1); |
318 | 339 |
|
319 |
- if (NULL == hd_malware.cfduid || NULL == hd_malware.session) { |
|
320 |
- fprintf(stderr, "invalid cfduid and/or session id values provided by clamav.net/presigned. Unable to continue submission."); |
|
321 |
- goto cleanup; |
|
322 |
- } |
|
323 |
- |
|
324 |
- len = strlen(hd_malware.cfduid) + strlen(hd_malware.session) + 3; |
|
325 |
- str = malloc(len); |
|
326 |
- if (str == NULL) { |
|
327 |
- fprintf(stderr, "No memory for GET presigned cookies\n"); |
|
328 |
- goto cleanup; |
|
329 |
- } |
|
330 |
- if (snprintf(str, len, "%s; %s;", hd_malware.cfduid, hd_malware.session) > len) { |
|
331 |
- fprintf(stderr, "snprintf() failed formatting GET presigned cookies\n"); |
|
332 |
- free(str); |
|
333 |
- goto cleanup; |
|
334 |
- } |
|
335 |
- curl_easy_setopt(clam_curl, CURLOPT_COOKIE, str); |
|
336 |
- free(str); |
|
337 |
- len = strlen(authenticity_token) + 15; |
|
338 |
- str = malloc(len); |
|
339 |
- if (str == NULL) { |
|
340 |
- fprintf(stderr, "No memory for GET presigned X-CSRF-Token\n"); |
|
341 |
- goto cleanup; |
|
342 |
- } |
|
343 |
- if (snprintf(str, len, "X-CSRF-Token: %s", authenticity_token) > len) { |
|
344 |
- fprintf(stderr, "snprintf() failed for GET presigned X-CSRF-Token\n"); |
|
345 |
- free(str); |
|
346 |
- goto cleanup; |
|
347 |
- } |
|
348 |
- slist = curl_slist_append(slist, str); |
|
349 |
- free(str); |
|
340 |
+ if (NULL != session_cookie) { |
|
341 |
+ curl_easy_setopt(clam_curl, CURLOPT_COOKIE, session_cookie); |
|
342 |
+ } |
|
343 |
+ |
|
344 |
+ /* Include an X-CSRF-Token header using the authenticity token retrieved with the presigned GET request */ |
|
345 |
+ len = strlen(authenticity_token) + strlen("X-CSRF-Token: ") + 1; |
|
346 |
+ authenticity_token_header = malloc(len); |
|
347 |
+ if (authenticity_token_header == NULL) { |
|
348 |
+ logg("!No memory for GET presigned X-CSRF-Token\n"); |
|
349 |
+ goto done; |
|
350 |
+ } |
|
351 |
+ if (snprintf(authenticity_token_header, len, "X-CSRF-Token: %s", authenticity_token) > len) { |
|
352 |
+ logg("!snprintf() failed for GET presigned X-CSRF-Token\n"); |
|
353 |
+ goto done; |
|
354 |
+ } |
|
355 |
+ slist = curl_slist_append(slist, authenticity_token_header); |
|
356 |
+ free(authenticity_token_header); |
|
357 |
+ authenticity_token_header = NULL; |
|
358 |
+ |
|
350 | 359 |
curl_easy_setopt(clam_curl, CURLOPT_HTTPHEADER, slist); |
351 | 360 |
curl_easy_setopt(clam_curl, CURLOPT_HEADERDATA, &hd_presigned); |
352 | 361 |
curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, header_cb); |
353 |
- if (malware == 1) |
|
354 |
- curl_easy_setopt(clam_curl, CURLOPT_REFERER, "https://www.clamav.net/reports/malware"); |
|
355 |
- else |
|
356 |
- curl_easy_setopt(clam_curl, CURLOPT_REFERER, "https://www.clamav.net/reports/fp"); |
|
362 |
+ curl_easy_setopt(clam_curl, CURLOPT_REFERER, url_for_auth_token); |
|
357 | 363 |
|
358 | 364 |
res = curl_easy_perform(clam_curl); |
359 | 365 |
if (res != CURLE_OK) { |
360 |
- fprintf(stderr, "Error in GET presigned: %s\n", curl_easy_strerror(res)); |
|
361 |
- goto cleanup; |
|
366 |
+ logg("!Error in GET reports: %s\n", curl_easy_strerror(res)); |
|
367 |
+ goto done; |
|
362 | 368 |
} |
363 | 369 |
curl_slist_free_all(slist); |
364 | 370 |
slist = NULL; |
365 | 371 |
|
366 |
- /*** The POST to AWS ***/ |
|
372 |
+ /* |
|
373 |
+ * POST the report to AWS |
|
374 |
+ */ |
|
367 | 375 |
ps_json_obj = json_tokener_parse(wd.str); |
368 | 376 |
if (ps_json_obj == NULL) { |
369 |
- fprintf(stderr, "Error in json_tokener_parse of %.*s\n", wd.len, wd.str); |
|
370 |
- goto cleanup; |
|
377 |
+ logg("!Error in json_tokener_parse of %.*s\n", wd.len, wd.str); |
|
378 |
+ goto done; |
|
371 | 379 |
} |
372 | 380 |
json_str = presigned_get_string(ps_json_obj, "key"); |
373 | 381 |
if (json_str == NULL) { |
374 |
- fprintf(stderr, "Error in presigned_get_string parsing key from json object\n"); |
|
375 |
- goto cleanup; |
|
382 |
+ logg("!Error in presigned_get_string parsing key from json object\n"); |
|
383 |
+ goto done; |
|
376 | 384 |
} |
377 | 385 |
sp = strchr(json_str, '/'); |
378 | 386 |
if (sp == NULL) { |
379 |
- fprintf(stderr, "Error: malformed 'key' string in GET presigned response (missing '/'.\n"); |
|
380 |
- goto cleanup; |
|
387 |
+ logg("!Error: malformed 'key' string in GET presigned response (missing '/'.\n"); |
|
388 |
+ goto done; |
|
381 | 389 |
} |
382 | 390 |
sp++; |
383 | 391 |
ep = strchr(sp, '-'); |
384 | 392 |
if (ep == NULL) { |
385 |
- fprintf(stderr, "Error: malformed 'key' string in GET presigned response (missing '-'.\n"); |
|
386 |
- goto cleanup; |
|
393 |
+ logg("!Error: malformed 'key' string in GET presigned response (missing '-'.\n"); |
|
394 |
+ goto done; |
|
387 | 395 |
} |
388 | 396 |
|
389 | 397 |
submissionID = malloc(ep - sp + 1); |
390 | 398 |
if (submissionID == NULL) { |
391 |
- fprintf(stderr, "Error: malloc submissionID.\n"); |
|
392 |
- goto cleanup; |
|
399 |
+ logg("!Error: malloc submissionID.\n"); |
|
400 |
+ goto done; |
|
393 | 401 |
} |
394 | 402 |
memcpy(submissionID, sp, ep - sp); |
395 | 403 |
submissionID[ep - sp] = '\0'; |
396 | 404 |
|
397 | 405 |
aws_curl = curl_easy_init(); |
398 | 406 |
if (!(aws_curl)) { |
399 |
- fprintf(stderr, "ERROR: Could not initialize libcurl POST presigned\n"); |
|
400 |
- goto cleanup; |
|
407 |
+ logg("!ERROR: Could not initialize libcurl POST presigned\n"); |
|
408 |
+ goto done; |
|
401 | 409 |
} |
402 | 410 |
|
403 | 411 |
if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_USERAGENT, userAgent)) { |
404 |
- fprintf(stderr, "!create_curl_handle: Failed to set CURLOPT_USERAGENT (%s)!\n", userAgent); |
|
412 |
+ logg("!!create_curl_handle: Failed to set CURLOPT_USERAGENT (%s)!\n", userAgent); |
|
405 | 413 |
} |
406 | 414 |
|
407 | 415 |
if (g_debug) { |
408 | 416 |
/* ask libcurl to show us the verbose output */ |
409 | 417 |
if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_VERBOSE, 1L)) { |
410 |
- fprintf(stderr, "!ERROR: Failed to set CURLOPT_VERBOSE!\n"); |
|
418 |
+ logg("!!ERROR: Failed to set CURLOPT_VERBOSE!\n"); |
|
411 | 419 |
} |
412 | 420 |
if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_STDERR, stdout)) { |
413 |
- fprintf(stderr, "!ERROR: Failed to direct curl debug output to stdout!\n"); |
|
421 |
+ logg("!!ERROR: Failed to direct curl debug output to stdout!\n"); |
|
414 | 422 |
} |
415 | 423 |
} |
416 | 424 |
|
417 | 425 |
if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1)) { |
418 |
- fprintf(stderr, "ERROR: Failed to set HTTP version to 1.1 (to prevent 2.0 responses which we don't yet parse properly)!\n"); |
|
426 |
+ logg("!ERROR: Failed to set HTTP version to 1.1 (to prevent 2.0 responses which we don't yet parse properly)!\n"); |
|
419 | 427 |
} |
420 | 428 |
|
421 | 429 |
#if defined(C_DARWIN) || defined(_WIN32) |
422 | 430 |
if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function)) { |
423 |
- fprintf(stderr, "ERROR: Failed to set SSL CTX function!\n"); |
|
431 |
+ logg("!ERROR: Failed to set SSL CTX function!\n"); |
|
424 | 432 |
} |
425 | 433 |
#else |
426 | 434 |
set_tls_ca_bundle(aws_curl); |
... | ... |
@@ -430,50 +473,50 @@ int main(int argc, char *argv[]) |
430 | 430 |
|
431 | 431 |
json_str = presigned_get_string(ps_json_obj, "acl"); |
432 | 432 |
if (json_str == NULL) { |
433 |
- fprintf(stderr, "Error in presigned_get_string parsing acl from json object\n"); |
|
434 |
- goto cleanup; |
|
433 |
+ logg("!Error in presigned_get_string parsing acl from json object\n"); |
|
434 |
+ goto done; |
|
435 | 435 |
} |
436 | 436 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "acl", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
437 | 437 |
|
438 | 438 |
json_str = presigned_get_string(ps_json_obj, "policy"); |
439 | 439 |
if (json_str == NULL) { |
440 |
- fprintf(stderr, "Error in presigned_get_string parsing policy from json object\n"); |
|
441 |
- goto cleanup; |
|
440 |
+ logg("!Error in presigned_get_string parsing policy from json object\n"); |
|
441 |
+ goto done; |
|
442 | 442 |
} |
443 | 443 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "policy", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
444 | 444 |
|
445 | 445 |
json_str = presigned_get_string(ps_json_obj, "x-amz-meta-original-filename"); |
446 | 446 |
if (json_str == NULL) { |
447 |
- fprintf(stderr, "Error in presigned_get_string parsing x-amz-meta-original-filename from json object\n"); |
|
448 |
- goto cleanup; |
|
447 |
+ logg("!Error in presigned_get_string parsing x-amz-meta-original-filename from json object\n"); |
|
448 |
+ goto done; |
|
449 | 449 |
} |
450 | 450 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-meta-original-filename", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
451 | 451 |
|
452 | 452 |
json_str = presigned_get_string(ps_json_obj, "x-amz-credential"); |
453 | 453 |
if (json_str == NULL) { |
454 |
- fprintf(stderr, "Error in presigned_get_string parsing x-amz-credential from json object\n"); |
|
455 |
- goto cleanup; |
|
454 |
+ logg("!Error in presigned_get_string parsing x-amz-credential from json object\n"); |
|
455 |
+ goto done; |
|
456 | 456 |
} |
457 | 457 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-credential", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
458 | 458 |
|
459 | 459 |
json_str = presigned_get_string(ps_json_obj, "x-amz-algorithm"); |
460 | 460 |
if (json_str == NULL) { |
461 |
- fprintf(stderr, "Error in presigned_get_string parsing x-amz-algorithm from json object\n"); |
|
462 |
- goto cleanup; |
|
461 |
+ logg("!Error in presigned_get_string parsing x-amz-algorithm from json object\n"); |
|
462 |
+ goto done; |
|
463 | 463 |
} |
464 | 464 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-algorithm", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
465 | 465 |
|
466 | 466 |
json_str = presigned_get_string(ps_json_obj, "x-amz-date"); |
467 | 467 |
if (json_str == NULL) { |
468 |
- fprintf(stderr, "Error in presigned_get_string parsing x-amz-date from json object\n"); |
|
469 |
- goto cleanup; |
|
468 |
+ logg("!Error in presigned_get_string parsing x-amz-date from json object\n"); |
|
469 |
+ goto done; |
|
470 | 470 |
} |
471 | 471 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-date", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
472 | 472 |
|
473 | 473 |
json_str = presigned_get_string(ps_json_obj, "x-amz-signature"); |
474 | 474 |
if (json_str == NULL) { |
475 |
- fprintf(stderr, "Error in presigned_get_string parsing x-amz-signature from json object\n"); |
|
476 |
- goto cleanup; |
|
475 |
+ logg("!Error in presigned_get_string parsing x-amz-signature from json object\n"); |
|
476 |
+ goto done; |
|
477 | 477 |
} |
478 | 478 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-signature", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
479 | 479 |
|
... | ... |
@@ -486,8 +529,8 @@ int main(int argc, char *argv[]) |
486 | 486 |
|
487 | 487 |
res = curl_easy_perform(aws_curl); |
488 | 488 |
if (res != CURLE_OK) { |
489 |
- fprintf(stderr, "Error in POST AWS: %s\n", curl_easy_strerror(res)); |
|
490 |
- goto cleanup; |
|
489 |
+ logg("!Error in POST AWS: %s\n", curl_easy_strerror(res)); |
|
490 |
+ goto done; |
|
491 | 491 |
} |
492 | 492 |
curl_slist_free_all(slist); |
493 | 493 |
slist = NULL; |
... | ... |
@@ -497,36 +540,30 @@ int main(int argc, char *argv[]) |
497 | 497 |
curl_easy_cleanup(aws_curl); |
498 | 498 |
aws_curl = NULL; |
499 | 499 |
json_object_put(ps_json_obj); |
500 |
- free(wd.str); |
|
501 |
- wd.str = NULL; |
|
500 |
+ |
|
501 |
+ if (wd.str != NULL) { |
|
502 |
+ free(wd.str); |
|
503 |
+ wd.str = NULL; |
|
504 |
+ } |
|
502 | 505 |
wd.len = 0; |
503 | 506 |
|
504 | 507 |
/*** The POST submit to clamav.net ***/ |
505 | 508 |
slist = curl_slist_append(slist, "Expect:"); |
506 |
- len = strlen(hd_malware.cfduid) + strlen(hd_malware.session) + 3; |
|
507 |
- str = malloc(len); |
|
508 |
- if (str == NULL) { |
|
509 |
- fprintf(stderr, "No memory for POST submit cookies.\n"); |
|
510 |
- goto cleanup; |
|
511 |
- } |
|
512 |
- if (snprintf(str, len, "%s; %s;", hd_malware.cfduid, hd_malware.session) > len) { |
|
513 |
- fprintf(stderr, "snprintf() failed formatting POST submit cookies\n"); |
|
514 |
- free(str); |
|
515 |
- goto cleanup; |
|
516 |
- } |
|
517 |
- curl_easy_setopt(clam_curl, CURLOPT_COOKIE, str); |
|
518 |
- free(str); |
|
509 |
+ |
|
510 |
+ if (NULL != session_cookie) { |
|
511 |
+ curl_easy_setopt(clam_curl, CURLOPT_COOKIE, session_cookie); |
|
512 |
+ } |
|
513 |
+ |
|
519 | 514 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "utf8", CURLFORM_COPYCONTENTS, "\x27\x13", CURLFORM_END); |
520 | 515 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "authenticity_token", CURLFORM_COPYCONTENTS, authenticity_token, CURLFORM_END); |
521 | 516 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "submissionID", CURLFORM_COPYCONTENTS, submissionID, CURLFORM_END); |
522 | 517 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "type", CURLFORM_COPYCONTENTS, malware ? "malware" : "fp", CURLFORM_END); |
523 | 518 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "sendername", CURLFORM_COPYCONTENTS, name, CURLFORM_END); |
524 | 519 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "email", CURLFORM_COPYCONTENTS, email, CURLFORM_END); |
525 |
- if (malware == 0) { |
|
526 |
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "virusname", CURLFORM_COPYCONTENTS, fpvname, CURLFORM_END); |
|
520 |
+ if (malware == true) { |
|
521 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "shareSample", CURLFORM_COPYCONTENTS, "on", CURLFORM_END); |
|
527 | 522 |
} else { |
528 |
- if (malware == 1) |
|
529 |
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "shareSample", CURLFORM_COPYCONTENTS, "on", CURLFORM_END); |
|
523 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "virusname", CURLFORM_COPYCONTENTS, fpvname, CURLFORM_END); |
|
530 | 524 |
} |
531 | 525 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "description", CURLFORM_COPYCONTENTS, "clamsubmit", CURLFORM_END); |
532 | 526 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "notify", CURLFORM_COPYCONTENTS, "on", CURLFORM_END); |
... | ... |
@@ -537,37 +574,43 @@ int main(int argc, char *argv[]) |
537 | 537 |
curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, NULL); |
538 | 538 |
res = curl_easy_perform(clam_curl); |
539 | 539 |
if (res != CURLE_OK) { |
540 |
- fprintf(stderr, "Error in POST submit: %s\n", curl_easy_strerror(res)); |
|
541 |
- goto cleanup; |
|
540 |
+ logg("!Error in POST submit: %s\n", curl_easy_strerror(res)); |
|
541 |
+ goto done; |
|
542 | 542 |
} else { |
543 | 543 |
long response_code; |
544 | 544 |
curl_easy_getinfo(clam_curl, CURLINFO_RESPONSE_CODE, &response_code); |
545 | 545 |
if (response_code / 100 == 3) { |
546 |
- curl_easy_getinfo(clam_curl, CURLINFO_REDIRECT_URL, &urlp); |
|
547 |
- if (urlp == NULL) { |
|
548 |
- fprintf(stderr, "POST submit Location URL is NULL.\n"); |
|
549 |
- goto cleanup; |
|
546 |
+ curl_easy_getinfo(clam_curl, CURLINFO_REDIRECT_URL, &url_for_auth_token); |
|
547 |
+ if (url_for_auth_token == NULL) { |
|
548 |
+ logg("!POST submit Location URL is NULL.\n"); |
|
549 |
+ goto done; |
|
550 | 550 |
} |
551 |
- sp = strstr(urlp, "/reports/"); |
|
551 |
+ sp = strstr(url_for_auth_token, "/reports/"); |
|
552 | 552 |
if (sp == NULL) { |
553 |
- fprintf(stderr, "POST submit Location URL is malformed.\n"); |
|
553 |
+ logg("!POST submit Location URL is malformed.\n"); |
|
554 | 554 |
} else if (!strcmp(sp, "/reports/success")) { |
555 |
- fprintf(stdout, "Submission success!\n"); |
|
555 |
+ logg("Submission success!\n"); |
|
556 | 556 |
status = 0; |
557 | 557 |
} else if (!strcmp(sp, "/reports/failure")) { |
558 |
- fprintf(stdout, "Submission failed\n"); |
|
558 |
+ logg("Submission failed\n"); |
|
559 | 559 |
} else { |
560 |
- fprintf(stdout, "Unknown submission status %s\n", sp); |
|
560 |
+ logg("Unknown submission status %s\n", sp); |
|
561 | 561 |
} |
562 | 562 |
} else { |
563 |
- fprintf(stderr, "Unexpected POST submit response code: %li\n", response_code); |
|
563 |
+ logg("!Unexpected POST submit response code: %li\n", response_code); |
|
564 | 564 |
} |
565 | 565 |
} |
566 | 566 |
|
567 |
-cleanup: |
|
567 |
+done: |
|
568 | 568 |
/* |
569 | 569 |
* Cleanup |
570 | 570 |
*/ |
571 |
+ if (authenticity_token_header != NULL) { |
|
572 |
+ free(authenticity_token_header); |
|
573 |
+ } |
|
574 |
+ if (session_cookie != NULL) { |
|
575 |
+ free(session_cookie); |
|
576 |
+ } |
|
571 | 577 |
if (slist != NULL) { |
572 | 578 |
curl_slist_free_all(slist); |
573 | 579 |
} |
... | ... |
@@ -587,15 +630,9 @@ cleanup: |
587 | 587 |
wd.str = NULL; |
588 | 588 |
wd.len = 0; |
589 | 589 |
} |
590 |
- if (hd_malware.cfduid != NULL) { |
|
591 |
- free(hd_malware.cfduid); |
|
592 |
- } |
|
593 | 590 |
if (hd_malware.session != NULL) { |
594 | 591 |
free(hd_malware.session); |
595 | 592 |
} |
596 |
- if (hd_presigned.cfduid != NULL) { |
|
597 |
- free(hd_presigned.cfduid); |
|
598 |
- } |
|
599 | 593 |
if (hd_presigned.session != NULL) { |
600 | 594 |
free(hd_presigned.session); |
601 | 595 |
} |