... | ... |
@@ -108,6 +108,13 @@ size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) |
108 | 108 |
return len; |
109 | 109 |
} |
110 | 110 |
|
111 |
+/** |
|
112 |
+ * @brief Parse a value from a JSON object, given a key. |
|
113 |
+ * |
|
114 |
+ * @param ps_json_obj The JSON object |
|
115 |
+ * @param key The Key |
|
116 |
+ * @return const char* The Value on Success, NULL on Failure. |
|
117 |
+ */ |
|
111 | 118 |
const char* presigned_get_string(json_object * ps_json_obj, char * key) |
112 | 119 |
{ |
113 | 120 |
json_object * json_obj = NULL; |
... | ... |
@@ -117,18 +124,17 @@ const char* presigned_get_string(json_object * ps_json_obj, char * key) |
117 | 117 |
json_str = json_object_get_string(json_obj); |
118 | 118 |
if (json_str == NULL) { |
119 | 119 |
fprintf(stderr, "Error: json_object_get_string() for %s.\n", key); |
120 |
- exit(1); |
|
121 | 120 |
} |
122 | 121 |
} else { |
123 | 122 |
fprintf(stderr, "Error: json_object_object_get_ex() for %s.\n", key); |
124 |
- exit(1); |
|
125 | 123 |
} |
126 | 124 |
return json_str; |
127 | 125 |
} |
128 | 126 |
|
129 | 127 |
int main(int argc, char *argv[]) |
130 | 128 |
{ |
131 |
- CURL *clam_curl, *aws_curl; |
|
129 |
+ int status = 1; |
|
130 |
+ CURL *clam_curl = NULL, *aws_curl = NULL; |
|
132 | 131 |
CURLcode res; |
133 | 132 |
int ch; |
134 | 133 |
struct curl_httppost *post=NULL, *last=NULL; |
... | ... |
@@ -146,7 +152,7 @@ int main(int argc, char *argv[]) |
146 | 146 |
char * submissionID = NULL; |
147 | 147 |
char * fpvname = NULL; |
148 | 148 |
char *sp, *ep, *str; |
149 |
- char * authenticity_token; |
|
149 |
+ char * authenticity_token = NULL; |
|
150 | 150 |
char * urlp; |
151 | 151 |
|
152 | 152 |
curl_global_init(CURL_GLOBAL_ALL); |
... | ... |
@@ -154,7 +160,7 @@ int main(int argc, char *argv[]) |
154 | 154 |
clam_curl = curl_easy_init(); |
155 | 155 |
if (clam_curl == NULL) { |
156 | 156 |
fprintf(stderr, "ERROR: Could not initialize libcurl.\n"); |
157 |
- exit(1); |
|
157 |
+ goto cleanup; |
|
158 | 158 |
} |
159 | 159 |
|
160 | 160 |
while ((ch = my_getopt(argc, argv, OPTS)) > 0) { |
... | ... |
@@ -200,7 +206,7 @@ int main(int argc, char *argv[]) |
200 | 200 |
filename = read_stream(); |
201 | 201 |
if (!(filename)) { |
202 | 202 |
fprintf(stderr, "ERROR: Unable to read stream\n"); |
203 |
- exit(1); |
|
203 |
+ goto cleanup; |
|
204 | 204 |
} |
205 | 205 |
fromStream=1; |
206 | 206 |
} |
... | ... |
@@ -208,9 +214,9 @@ int main(int argc, char *argv[]) |
208 | 208 |
|
209 | 209 |
/*** The GET malware|fp ***/ |
210 | 210 |
if (malware == 1) |
211 |
- urlp = "http://www.clamav.net/reports/malware"; |
|
211 |
+ urlp = "https://www.clamav.net/reports/malware"; |
|
212 | 212 |
else |
213 |
- urlp = "http://www.clamav.net/reports/fp"; |
|
213 |
+ urlp = "https://www.clamav.net/reports/fp"; |
|
214 | 214 |
curl_easy_setopt(clam_curl, CURLOPT_URL, urlp); |
215 | 215 |
curl_easy_setopt(clam_curl, CURLOPT_HTTPGET, 1); |
216 | 216 |
curl_easy_setopt(clam_curl, CURLOPT_WRITEDATA, &wd); |
... | ... |
@@ -218,31 +224,31 @@ int main(int argc, char *argv[]) |
218 | 218 |
curl_easy_setopt(clam_curl, CURLOPT_HEADERDATA, &hd_malware); |
219 | 219 |
curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, header_cb); |
220 | 220 |
res = curl_easy_perform(clam_curl); |
221 |
- if (res) { |
|
221 |
+ if (res != CURLE_OK) { |
|
222 | 222 |
fprintf(stderr, "Error in GET %s: %s\n", urlp , curl_easy_strerror(res)); |
223 |
- exit(1); |
|
223 |
+ goto cleanup; |
|
224 | 224 |
} |
225 | 225 |
if (wd.str != NULL) { |
226 | 226 |
sp = strstr(wd.str, "name=\"authenticity_token\""); |
227 | 227 |
if (sp == NULL) { |
228 | 228 |
fprintf (stderr, "Authenticity token element not found.\n"); |
229 |
- exit(1); |
|
229 |
+ goto cleanup; |
|
230 | 230 |
} |
231 | 231 |
sp = strstr(sp, "value="); |
232 | 232 |
if (sp == NULL) { |
233 | 233 |
fprintf (stderr, "Authenticity token value not found.\n"); |
234 |
- exit(1); |
|
234 |
+ goto cleanup; |
|
235 | 235 |
} |
236 | 236 |
sp += 7; |
237 | 237 |
ep = strchr(sp, '"'); |
238 | 238 |
if (ep == NULL) { |
239 | 239 |
fprintf (stderr, "Authenticity token malformed.\n"); |
240 |
- exit(1); |
|
240 |
+ goto cleanup; |
|
241 | 241 |
} |
242 | 242 |
authenticity_token = malloc(ep-sp+1); |
243 | 243 |
if (authenticity_token == NULL) { |
244 | 244 |
fprintf (stderr, "no memory for authenticity token.\n"); |
245 |
- exit(1); |
|
245 |
+ goto cleanup; |
|
246 | 246 |
} |
247 | 247 |
memcpy(authenticity_token, sp, ep-sp); |
248 | 248 |
authenticity_token[ep-sp] = '\0'; |
... | ... |
@@ -255,25 +261,25 @@ int main(int argc, char *argv[]) |
255 | 255 |
|
256 | 256 |
/*** The GET presigned ***/ |
257 | 257 |
if (malware == 1) |
258 |
- curl_easy_setopt(clam_curl, CURLOPT_URL, "http://www.clamav.net/presigned?type=malware"); |
|
258 |
+ curl_easy_setopt(clam_curl, CURLOPT_URL, "https://www.clamav.net/presigned?type=malware"); |
|
259 | 259 |
else |
260 |
- curl_easy_setopt(clam_curl, CURLOPT_URL, "http://www.clamav.net/presigned?type=fp"); |
|
260 |
+ curl_easy_setopt(clam_curl, CURLOPT_URL, "https://www.clamav.net/presigned?type=fp"); |
|
261 | 261 |
curl_easy_setopt(clam_curl, CURLOPT_HTTPGET, 1); |
262 | 262 |
|
263 | 263 |
if (NULL == hd_malware.cfduid || NULL == hd_malware.session) { |
264 | 264 |
fprintf (stderr, "invalid cfduid and/or session id values provided by clamav.net/presigned. Unable to continue submission."); |
265 |
- exit(1); |
|
265 |
+ goto cleanup; |
|
266 | 266 |
} |
267 | 267 |
|
268 | 268 |
len = strlen(hd_malware.cfduid) + strlen(hd_malware.session) + 3; |
269 | 269 |
str = malloc(len); |
270 | 270 |
if (str == NULL) { |
271 | 271 |
fprintf(stderr, "No memory for GET presigned cookies\n"); |
272 |
- exit(1); |
|
272 |
+ goto cleanup; |
|
273 | 273 |
} |
274 | 274 |
if (snprintf(str, len, "%s; %s;", hd_malware.cfduid, hd_malware.session) > len) { |
275 | 275 |
fprintf(stderr, "snprintf() failed formatting GET presigned cookies\n"); |
276 |
- exit(1); |
|
276 |
+ goto cleanup; |
|
277 | 277 |
} |
278 | 278 |
curl_easy_setopt(clam_curl, CURLOPT_COOKIE, str); |
279 | 279 |
free(str); |
... | ... |
@@ -281,11 +287,12 @@ int main(int argc, char *argv[]) |
281 | 281 |
str = malloc(len); |
282 | 282 |
if (str == NULL) { |
283 | 283 |
fprintf(stderr, "No memory for GET presigned X-CSRF-Token\n"); |
284 |
- exit(1); |
|
284 |
+ goto cleanup; |
|
285 | 285 |
} |
286 | 286 |
if (snprintf(str, len, "X-CSRF-Token: %s", authenticity_token) > len) { |
287 | 287 |
fprintf(stderr, "snprintf() failed for GET presigned X-CSRF-Token\n"); |
288 |
- exit(1); |
|
288 |
+ free(str); |
|
289 |
+ goto cleanup; |
|
289 | 290 |
} |
290 | 291 |
slist = curl_slist_append(slist, str); |
291 | 292 |
free(str); |
... | ... |
@@ -293,14 +300,14 @@ int main(int argc, char *argv[]) |
293 | 293 |
curl_easy_setopt(clam_curl, CURLOPT_HEADERDATA, &hd_presigned); |
294 | 294 |
curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, header_cb); |
295 | 295 |
if (malware ==1) |
296 |
- curl_easy_setopt(clam_curl, CURLOPT_REFERER, "http://www.clamav.net/reports/malware"); |
|
296 |
+ curl_easy_setopt(clam_curl, CURLOPT_REFERER, "https://www.clamav.net/reports/malware"); |
|
297 | 297 |
else |
298 |
- curl_easy_setopt(clam_curl, CURLOPT_REFERER, "http://www.clamav.net/reports/fp"); |
|
298 |
+ curl_easy_setopt(clam_curl, CURLOPT_REFERER, "https://www.clamav.net/reports/fp"); |
|
299 | 299 |
|
300 | 300 |
res = curl_easy_perform(clam_curl); |
301 |
- if (res) { |
|
301 |
+ if (res != CURLE_OK) { |
|
302 | 302 |
fprintf(stderr, "Error in GET presigned: %s\n", curl_easy_strerror(res)); |
303 |
- exit(1); |
|
303 |
+ goto cleanup; |
|
304 | 304 |
} |
305 | 305 |
curl_slist_free_all(slist); |
306 | 306 |
slist = NULL; |
... | ... |
@@ -310,58 +317,99 @@ int main(int argc, char *argv[]) |
310 | 310 |
ps_json_obj = json_tokener_parse(wd.str); |
311 | 311 |
if (ps_json_obj == NULL) { |
312 | 312 |
fprintf(stderr, "Error in json_tokener_parse of %.*s\n", wd.len, wd.str); |
313 |
- exit(1); |
|
313 |
+ goto cleanup; |
|
314 | 314 |
} |
315 | 315 |
json_str = presigned_get_string(ps_json_obj, "key"); |
316 |
+ if (json_str == NULL) { |
|
317 |
+ fprintf(stderr, "Error in presigned_get_string parsing key from json object\n"); |
|
318 |
+ goto cleanup; |
|
319 |
+ } |
|
316 | 320 |
sp = strchr(json_str, '/'); |
317 | 321 |
if (sp == NULL) { |
318 | 322 |
fprintf(stderr, "Error: malformed 'key' string in GET presigned response (missing '/'.\n"); |
319 |
- exit (1); |
|
323 |
+ goto cleanup; |
|
320 | 324 |
} |
321 | 325 |
sp++; |
322 | 326 |
ep = strchr(sp, '-'); |
323 | 327 |
if (ep == NULL) { |
324 | 328 |
fprintf(stderr, "Error: malformed 'key' string in GET presigned response (missing '-'.\n"); |
325 |
- exit (1); |
|
329 |
+ goto cleanup; |
|
326 | 330 |
} |
327 | 331 |
submissionID = malloc(ep-sp+1); |
328 | 332 |
if (submissionID == NULL) { |
329 | 333 |
fprintf(stderr, "Error: malloc submissionID.\n"); |
330 |
- exit (1); |
|
334 |
+ goto cleanup; |
|
331 | 335 |
} |
332 | 336 |
memcpy(submissionID, sp, ep-sp); |
333 | 337 |
submissionID[ep-sp] = '\0'; |
334 | 338 |
aws_curl = curl_easy_init(); |
335 | 339 |
if (!(aws_curl)) { |
336 | 340 |
fprintf(stderr, "ERROR: Could not initialize libcurl POST presigned\n"); |
337 |
- exit(1); |
|
341 |
+ goto cleanup; |
|
338 | 342 |
} |
339 | 343 |
submissionID[ep-sp] = '\0'; |
340 | 344 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "key", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
345 |
+ |
|
341 | 346 |
json_str = presigned_get_string(ps_json_obj, "acl"); |
347 |
+ if (json_str == NULL) { |
|
348 |
+ fprintf(stderr, "Error in presigned_get_string parsing acl from json object\n"); |
|
349 |
+ goto cleanup; |
|
350 |
+ } |
|
342 | 351 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "acl", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
352 |
+ |
|
343 | 353 |
json_str = presigned_get_string(ps_json_obj, "policy"); |
354 |
+ if (json_str == NULL) { |
|
355 |
+ fprintf(stderr, "Error in presigned_get_string parsing policy from json object\n"); |
|
356 |
+ goto cleanup; |
|
357 |
+ } |
|
344 | 358 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "policy", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
359 |
+ |
|
345 | 360 |
json_str = presigned_get_string(ps_json_obj, "x-amz-meta-original-filename"); |
361 |
+ if (json_str == NULL) { |
|
362 |
+ fprintf(stderr, "Error in presigned_get_string parsing x-amz-meta-original-filename from json object\n"); |
|
363 |
+ goto cleanup; |
|
364 |
+ } |
|
346 | 365 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-meta-original-filename", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
366 |
+ |
|
347 | 367 |
json_str = presigned_get_string(ps_json_obj, "x-amz-credential"); |
368 |
+ if (json_str == NULL) { |
|
369 |
+ fprintf(stderr, "Error in presigned_get_string parsing x-amz-credential from json object\n"); |
|
370 |
+ goto cleanup; |
|
371 |
+ } |
|
348 | 372 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-credential", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
373 |
+ |
|
349 | 374 |
json_str = presigned_get_string(ps_json_obj, "x-amz-algorithm"); |
375 |
+ if (json_str == NULL) { |
|
376 |
+ fprintf(stderr, "Error in presigned_get_string parsing x-amz-algorithm from json object\n"); |
|
377 |
+ goto cleanup; |
|
378 |
+ } |
|
350 | 379 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-algorithm", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
380 |
+ |
|
351 | 381 |
json_str = presigned_get_string(ps_json_obj, "x-amz-date"); |
382 |
+ if (json_str == NULL) { |
|
383 |
+ fprintf(stderr, "Error in presigned_get_string parsing x-amz-date from json object\n"); |
|
384 |
+ goto cleanup; |
|
385 |
+ } |
|
352 | 386 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-date", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
387 |
+ |
|
353 | 388 |
json_str = presigned_get_string(ps_json_obj, "x-amz-signature"); |
389 |
+ if (json_str == NULL) { |
|
390 |
+ fprintf(stderr, "Error in presigned_get_string parsing x-amz-signature from json object\n"); |
|
391 |
+ goto cleanup; |
|
392 |
+ } |
|
354 | 393 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-signature", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
394 |
+ |
|
355 | 395 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_FILE, filename, CURLFORM_END); |
396 |
+ |
|
356 | 397 |
slist = curl_slist_append(slist, "Expect:"); |
357 | 398 |
curl_easy_setopt(aws_curl, CURLOPT_HTTPHEADER, slist); |
358 |
- curl_easy_setopt(aws_curl, CURLOPT_URL, "http://clamav-site.s3.amazonaws.com/"); |
|
399 |
+ curl_easy_setopt(aws_curl, CURLOPT_URL, "https://clamav-site.s3.amazonaws.com/"); |
|
359 | 400 |
curl_easy_setopt(aws_curl, CURLOPT_HTTPPOST, post); |
360 | 401 |
|
361 | 402 |
res = curl_easy_perform(aws_curl); |
362 |
- if (res) { |
|
403 |
+ if (res != CURLE_OK) { |
|
363 | 404 |
fprintf(stderr, "Error in POST AWS: %s\n", curl_easy_strerror(res)); |
364 |
- exit(1); |
|
405 |
+ goto cleanup; |
|
365 | 406 |
} |
366 | 407 |
curl_slist_free_all(slist); |
367 | 408 |
slist = NULL; |
... | ... |
@@ -381,11 +429,11 @@ int main(int argc, char *argv[]) |
381 | 381 |
str = malloc(len); |
382 | 382 |
if (str == NULL) { |
383 | 383 |
fprintf(stderr, "No memory for POST submit cookies.\n"); |
384 |
- exit(1); |
|
384 |
+ goto cleanup; |
|
385 | 385 |
} |
386 | 386 |
if (snprintf(str, len, "%s; %s;", hd_malware.cfduid, hd_malware.session) > len) { |
387 | 387 |
fprintf(stderr, "snprintf() failed formatting POST submit cookies\n"); |
388 |
- exit(1); |
|
388 |
+ goto cleanup; |
|
389 | 389 |
} |
390 | 390 |
curl_easy_setopt(clam_curl, CURLOPT_COOKIE, str); |
391 | 391 |
free(str); |
... | ... |
@@ -405,13 +453,13 @@ int main(int argc, char *argv[]) |
405 | 405 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "notify", CURLFORM_COPYCONTENTS, "on", CURLFORM_END); |
406 | 406 |
curl_formadd(&post, &last, CURLFORM_COPYNAME, "privacy", CURLFORM_COPYCONTENTS, "on", CURLFORM_END); |
407 | 407 |
curl_easy_setopt(clam_curl, CURLOPT_HTTPHEADER, slist); |
408 |
- curl_easy_setopt(clam_curl, CURLOPT_URL, "http://www.clamav.net/reports/submit"); |
|
408 |
+ curl_easy_setopt(clam_curl, CURLOPT_URL, "https://www.clamav.net/reports/submit"); |
|
409 | 409 |
curl_easy_setopt(clam_curl, CURLOPT_HTTPPOST, post); |
410 | 410 |
curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, NULL); |
411 | 411 |
res = curl_easy_perform(clam_curl); |
412 |
- if (res) { |
|
412 |
+ if (res != CURLE_OK) { |
|
413 | 413 |
fprintf(stderr, "Error in POST submit: %s\n", curl_easy_strerror(res)); |
414 |
- exit(1); |
|
414 |
+ goto cleanup; |
|
415 | 415 |
} else { |
416 | 416 |
long response_code; |
417 | 417 |
curl_easy_getinfo(clam_curl, CURLINFO_RESPONSE_CODE, &response_code); |
... | ... |
@@ -419,43 +467,75 @@ int main(int argc, char *argv[]) |
419 | 419 |
curl_easy_getinfo(clam_curl, CURLINFO_REDIRECT_URL, &urlp); |
420 | 420 |
if (urlp == NULL) { |
421 | 421 |
fprintf(stderr, "POST submit Location URL is NULL.\n"); |
422 |
- exit(1); |
|
422 |
+ goto cleanup; |
|
423 | 423 |
} |
424 | 424 |
sp = strstr(urlp, "/reports/"); |
425 | 425 |
if (sp == NULL) { |
426 | 426 |
fprintf(stderr, "POST submit Location URL is malformed.\n"); |
427 |
- exit(1); |
|
428 | 427 |
} |
429 |
- if (!strcmp(sp, "/reports/success")) |
|
428 |
+ else if (!strcmp(sp, "/reports/success")) { |
|
430 | 429 |
fprintf(stdout, "Submission success!\n"); |
431 |
- else if (!strcmp(sp, "/reports/failure")) |
|
430 |
+ status = 0; |
|
431 |
+ } |
|
432 |
+ else if (!strcmp(sp, "/reports/failure")) { |
|
432 | 433 |
fprintf(stdout, "Submission failed\n"); |
433 |
- else |
|
434 |
+ } |
|
435 |
+ else { |
|
434 | 436 |
fprintf(stdout, "Unknown submission status %s\n", sp); |
437 |
+ } |
|
435 | 438 |
} |
436 |
- else |
|
439 |
+ else { |
|
437 | 440 |
fprintf(stderr, "Unexpected POST submit response code: %li\n", response_code); |
441 |
+ } |
|
438 | 442 |
} |
439 |
- curl_slist_free_all(slist); |
|
440 |
- curl_formfree(post); |
|
441 |
- curl_easy_cleanup(clam_curl); |
|
443 |
+ |
|
444 |
+cleanup: |
|
445 |
+ /* |
|
446 |
+ * Cleanup |
|
447 |
+ */ |
|
448 |
+ if (slist != NULL) { |
|
449 |
+ curl_slist_free_all(slist); |
|
450 |
+ } |
|
451 |
+ if (post != NULL) { |
|
452 |
+ curl_formfree(post); |
|
453 |
+ } |
|
454 |
+ if (clam_curl != NULL) { |
|
455 |
+ curl_easy_cleanup(clam_curl); |
|
456 |
+ } |
|
457 |
+ if (aws_curl != NULL) { |
|
458 |
+ curl_easy_cleanup(aws_curl); |
|
459 |
+ } |
|
460 |
+ curl_global_cleanup(); |
|
461 |
+ |
|
442 | 462 |
if (wd.str != NULL) { |
443 | 463 |
free(wd.str); |
444 | 464 |
wd.str = NULL; |
445 | 465 |
wd.len = 0; |
446 | 466 |
} |
447 |
- free(hd_malware.cfduid); |
|
448 |
- free(hd_malware.session); |
|
449 |
- free(hd_presigned.cfduid); |
|
450 |
- free(hd_presigned.session); |
|
451 |
- free(submissionID); |
|
452 |
- free(authenticity_token); |
|
453 |
- if (fromStream) { |
|
467 |
+ if (hd_malware.cfduid != NULL) { |
|
468 |
+ free(hd_malware.cfduid); |
|
469 |
+ } |
|
470 |
+ if (hd_malware.session != NULL) { |
|
471 |
+ free(hd_malware.session); |
|
472 |
+ } |
|
473 |
+ if (hd_presigned.cfduid != NULL) { |
|
474 |
+ free(hd_presigned.cfduid); |
|
475 |
+ } |
|
476 |
+ if (hd_presigned.session != NULL) { |
|
477 |
+ free(hd_presigned.session); |
|
478 |
+ } |
|
479 |
+ if (submissionID != NULL) { |
|
480 |
+ free(submissionID); |
|
481 |
+ } |
|
482 |
+ if (authenticity_token != NULL) { |
|
483 |
+ free(authenticity_token); |
|
484 |
+ } |
|
485 |
+ if ((fromStream != 0) && (filename != NULL)) { |
|
454 | 486 |
remove(filename); |
455 | 487 |
free(filename); |
456 | 488 |
} |
457 | 489 |
|
458 |
- return 0; |
|
490 |
+ return status; |
|
459 | 491 |
} |
460 | 492 |
|
461 | 493 |
|