... | ... |
@@ -10,21 +10,33 @@ |
10 | 10 |
#include "shared/misc.h" |
11 | 11 |
#include "shared/getopt.h" |
12 | 12 |
|
13 |
-#define OPTS "e:p:n:N:H:h?v" |
|
13 |
+#define OPTS "e:p:n:N:V:H:h?v" |
|
14 | 14 |
|
15 | 15 |
char *read_stream(void); |
16 | 16 |
void usage(char *name); |
17 | 17 |
void version(void); |
18 | 18 |
|
19 |
+typedef struct _header_data { |
|
20 |
+ int len; |
|
21 |
+ char * cfduid; |
|
22 |
+ char * session; |
|
23 |
+} header_data; |
|
24 |
+ |
|
25 |
+typedef struct _write_data { |
|
26 |
+ int len; |
|
27 |
+ char * str; |
|
28 |
+} write_data; |
|
29 |
+ |
|
19 | 30 |
void usage(char *name) |
20 | 31 |
{ |
21 |
- fprintf(stderr, "USAGE: %s -hHinp?\n", name); |
|
32 |
+ fprintf(stderr, "USAGE: %s -hHinpVv?\n", name); |
|
22 | 33 |
fprintf(stderr, "OPTIONS:\n"); |
23 | 34 |
fprintf(stderr, " -e [EMAIL]\tYour email address (required)\n"); |
24 | 35 |
fprintf(stderr, " -h or -?\tShow the help text\n"); |
25 | 36 |
fprintf(stderr, " -n [FILE]\tSubmit a false negative (FN)\n"); |
26 |
- fprintf(stderr, " -N [NAME]\tYour name (required)\n"); |
|
27 |
- fprintf(stderr, " -p [FILE]\tSubmit a fase positive (FP)\n"); |
|
37 |
+ fprintf(stderr, " -N [NAME]\tYour name contained in quotation marks (required)\n"); |
|
38 |
+ fprintf(stderr, " -p [FILE]\tSubmit a false positive (FP)\n"); |
|
39 |
+ fprintf(stderr, " -V [NAME] \tDetected virus name(required with -p)\n"); |
|
28 | 40 |
fprintf(stderr, " -v\t\tShow version number and exit\n"); |
29 | 41 |
fprintf(stderr, "You must specify -n or -p. Both are mutually exclusive. Pass in - as the filename for stdin.\n"); |
30 | 42 |
exit(0); |
... | ... |
@@ -36,21 +48,106 @@ void version(void) |
36 | 36 |
exit(0); |
37 | 37 |
} |
38 | 38 |
|
39 |
+size_t header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) |
|
40 |
+{ |
|
41 |
+ int len = size*nmemb; |
|
42 |
+ char *sp, *ep, *mem; |
|
43 |
+ header_data *hd = (header_data *) userdata; |
|
44 |
+ const char *set_cookie = "Set-Cookie:"; |
|
45 |
+ int clen = strlen(set_cookie); |
|
46 |
+ |
|
47 |
+ if (len > clen) { |
|
48 |
+ if (strncmp(ptr, set_cookie, clen)) |
|
49 |
+ return len; |
|
50 |
+ sp = ptr + clen + 1; |
|
51 |
+ ep = strchr(sp, ';'); |
|
52 |
+ if (ep == NULL) { |
|
53 |
+ fprintf(stderr, "header_cb(): malformed cookie\n"); |
|
54 |
+ return 0; |
|
55 |
+ } |
|
56 |
+ mem = malloc(ep-sp+1); |
|
57 |
+ if (mem == NULL) { |
|
58 |
+ fprintf(stderr, "header_cb(): malloc failed\n"); |
|
59 |
+ return 0; |
|
60 |
+ } |
|
61 |
+ memcpy(mem, sp, ep-sp); |
|
62 |
+ mem[ep-sp] = '\0'; |
|
63 |
+ if (!strncmp(mem, "__cfduid", 8)) |
|
64 |
+ hd->cfduid = mem; |
|
65 |
+ else if (!strncmp(mem, "_clamav-net_session", strlen("_clamav-net_session"))) |
|
66 |
+ hd->session = mem; |
|
67 |
+ else |
|
68 |
+ fprintf(stderr, "header_cb(): unrecognized cookie\n"); |
|
69 |
+ } |
|
70 |
+ return len; |
|
71 |
+} |
|
72 |
+ |
|
73 |
+size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) |
|
74 |
+{ |
|
75 |
+ int len = size*nmemb; |
|
76 |
+ char * str; |
|
77 |
+ write_data *wd = (write_data *) userdata; |
|
78 |
+ |
|
79 |
+ if (len) { |
|
80 |
+ str = realloc(wd->str, wd->len + len + 1); |
|
81 |
+ if (str == NULL) { |
|
82 |
+ fprintf (stderr, "write_cb() realloc failure\n"); |
|
83 |
+ return 0; |
|
84 |
+ } |
|
85 |
+ memcpy(str + wd->len, ptr, len); |
|
86 |
+ str[wd->len + len] = '\0'; |
|
87 |
+ wd->str = str; |
|
88 |
+ wd->len += len; |
|
89 |
+ } |
|
90 |
+ return len; |
|
91 |
+} |
|
92 |
+ |
|
93 |
+const char* presigned_get_string(json_object * ps_json_obj, char * key) |
|
94 |
+{ |
|
95 |
+ json_object * json_obj = NULL; |
|
96 |
+ const char * json_str = NULL; |
|
97 |
+ |
|
98 |
+ if (json_object_object_get_ex(ps_json_obj, key, &json_obj)) { |
|
99 |
+ json_str = json_object_get_string(json_obj); |
|
100 |
+ if (json_str == NULL) { |
|
101 |
+ fprintf(stderr, "Error: json_object_get_string() for %s.\n", key); |
|
102 |
+ exit(1); |
|
103 |
+ } |
|
104 |
+ } else { |
|
105 |
+ fprintf(stderr, "Error: json_object_object_get_ex() for %s.\n", key); |
|
106 |
+ exit(1); |
|
107 |
+ } |
|
108 |
+ return json_str; |
|
109 |
+} |
|
110 |
+ |
|
39 | 111 |
int main(int argc, char *argv[]) |
40 | 112 |
{ |
41 |
- CURL *curl; |
|
113 |
+ CURL *clam_curl, *aws_curl; |
|
42 | 114 |
CURLcode res; |
43 | 115 |
int ch; |
44 | 116 |
struct curl_httppost *post=NULL, *last=NULL; |
45 | 117 |
struct curl_slist *slist = NULL; |
46 | 118 |
char *name=NULL, *email=NULL, *filename=NULL; |
47 | 119 |
int setURL=0, fromStream=0; |
120 |
+ const char * json_str; |
|
121 |
+ write_data wd = {0, NULL}; |
|
122 |
+ header_data hd_malware = {0, NULL, NULL}; |
|
123 |
+ header_data hd_presigned = {0, NULL, NULL}; |
|
124 |
+ json_object * ps_json_obj = NULL; |
|
125 |
+ json_object * json_obj = NULL; |
|
126 |
+ int malware = 0; |
|
127 |
+ int len = 0; |
|
128 |
+ char * submissionID = NULL; |
|
129 |
+ char * fpvname = NULL; |
|
130 |
+ char *sp, *ep, *str; |
|
131 |
+ char * authenticity_token; |
|
132 |
+ char * urlp; |
|
48 | 133 |
|
49 | 134 |
curl_global_init(CURL_GLOBAL_ALL); |
50 | 135 |
|
51 |
- curl = curl_easy_init(); |
|
52 |
- if (!(curl)) { |
|
53 |
- fprintf(stderr, "ERROR: Could not initialize libcurl\n"); |
|
136 |
+ clam_curl = curl_easy_init(); |
|
137 |
+ if (clam_curl == NULL) { |
|
138 |
+ fprintf(stderr, "ERROR: Could not initialize libcurl.\n"); |
|
54 | 139 |
exit(1); |
55 | 140 |
} |
56 | 141 |
|
... | ... |
@@ -58,6 +155,7 @@ int main(int argc, char *argv[]) |
58 | 58 |
switch (ch) { |
59 | 59 |
case 'v': |
60 | 60 |
version(); |
61 |
+ break; |
|
61 | 62 |
case 'e': |
62 | 63 |
email = optarg; |
63 | 64 |
break; |
... | ... |
@@ -67,20 +165,16 @@ int main(int argc, char *argv[]) |
67 | 67 |
case 'p': |
68 | 68 |
if (setURL) |
69 | 69 |
usage(argv[0]); |
70 |
- |
|
71 | 70 |
filename = optarg; |
72 |
- |
|
73 |
- curl_easy_setopt(curl, CURLOPT_URL, "http://cgi.clamav.net/sendfp.cgi"); |
|
74 |
- setURL=1; |
|
75 | 71 |
break; |
76 | 72 |
case 'n': |
77 | 73 |
if (setURL) |
78 | 74 |
usage(argv[0]); |
79 |
- |
|
75 |
+ malware = 1; |
|
80 | 76 |
filename = optarg; |
81 |
- |
|
82 |
- curl_easy_setopt(curl, CURLOPT_URL, "http://cgi.clamav.net/sendmalware.cgi"); |
|
83 |
- setURL=1; |
|
77 |
+ break; |
|
78 |
+ case 'V': |
|
79 |
+ fpvname = optarg; |
|
84 | 80 |
break; |
85 | 81 |
case 'h': |
86 | 82 |
case '?': |
... | ... |
@@ -92,47 +186,258 @@ int main(int argc, char *argv[]) |
92 | 92 |
if (!(name) || !(email) || !(filename)) |
93 | 93 |
usage(argv[0]); |
94 | 94 |
|
95 |
+ if (malware == 0 && fpvname == NULL) { |
|
96 |
+ fprintf(stderr, "Detected virus name(-V) required for false positive submissions.\n"); |
|
97 |
+ usage(argv[0]); |
|
98 |
+ } |
|
95 | 99 |
if (strlen(filename) == 1 && filename[0] == '-') { |
96 | 100 |
filename = read_stream(); |
97 | 101 |
if (!(filename)) { |
98 | 102 |
fprintf(stderr, "ERROR: Unable to read stream\n"); |
99 | 103 |
exit(1); |
100 | 104 |
} |
101 |
- |
|
102 | 105 |
fromStream=1; |
103 | 106 |
} |
104 | 107 |
|
105 |
- slist = curl_slist_append(slist, "Expect:"); |
|
106 |
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); |
|
107 | 108 |
|
108 |
- if (curl_formadd(&post, &last, CURLFORM_COPYNAME, "sendername", CURLFORM_COPYCONTENTS, name, CURLFORM_END)) { |
|
109 |
- fprintf(stderr, "Unable to specify name in libcurl form for file %s\n", optarg); |
|
110 |
- goto end; |
|
109 |
+ /*** The GET malware|fp ***/ |
|
110 |
+ if (malware == 1) |
|
111 |
+ urlp = "http://www.clamav.net/reports/malware"; |
|
112 |
+ else |
|
113 |
+ urlp = "http://www.clamav.net/reports/fp"; |
|
114 |
+ curl_easy_setopt(clam_curl, CURLOPT_URL, urlp); |
|
115 |
+ curl_easy_setopt(clam_curl, CURLOPT_HTTPGET, 1); |
|
116 |
+ curl_easy_setopt(clam_curl, CURLOPT_WRITEDATA, &wd); |
|
117 |
+ curl_easy_setopt(clam_curl, CURLOPT_WRITEFUNCTION, write_cb); |
|
118 |
+ curl_easy_setopt(clam_curl, CURLOPT_HEADERDATA, &hd_malware); |
|
119 |
+ curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, header_cb); |
|
120 |
+ res = curl_easy_perform(clam_curl); |
|
121 |
+ if (res) { |
|
122 |
+ fprintf(stderr, "Error in GET %s: %s\n", urlp , curl_easy_strerror(res)); |
|
123 |
+ exit(1); |
|
111 | 124 |
} |
112 |
- |
|
113 |
- if (curl_formadd(&post, &last, CURLFORM_COPYNAME, "email", CURLFORM_COPYCONTENTS, email, CURLFORM_END)) { |
|
114 |
- fprintf(stderr, "Unable to specify email in libcurl form for file %s\n", optarg); |
|
115 |
- goto end; |
|
125 |
+ if (wd.str != NULL) { |
|
126 |
+ sp = strstr(wd.str, "name=\"authenticity_token\""); |
|
127 |
+ if (sp == NULL) { |
|
128 |
+ fprintf (stderr, "Authenticity token element not found.\n"); |
|
129 |
+ exit(1); |
|
130 |
+ } |
|
131 |
+ sp = strstr(sp, "value="); |
|
132 |
+ if (sp == NULL) { |
|
133 |
+ fprintf (stderr, "Authenticity token value not found.\n"); |
|
134 |
+ exit(1); |
|
135 |
+ } |
|
136 |
+ sp += 7; |
|
137 |
+ ep = strchr(sp, '"'); |
|
138 |
+ if (ep == NULL) { |
|
139 |
+ fprintf (stderr, "Authenticity token malformed.\n"); |
|
140 |
+ exit(1); |
|
141 |
+ } |
|
142 |
+ authenticity_token = malloc(ep-sp+1); |
|
143 |
+ if (authenticity_token == NULL) { |
|
144 |
+ fprintf (stderr, "no memory for authenticity token.\n"); |
|
145 |
+ exit(1); |
|
146 |
+ } |
|
147 |
+ memcpy(authenticity_token, sp, ep-sp); |
|
148 |
+ authenticity_token[ep-sp] = '\0'; |
|
149 |
+ free (wd.str); |
|
150 |
+ wd.str = NULL; |
|
116 | 151 |
} |
117 |
- |
|
118 |
- if (curl_formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_FILE, filename, CURLFORM_END)) { |
|
119 |
- fprintf(stderr, "Unable to specify file path in libcurl form for file %s\n", optarg); |
|
120 |
- goto end; |
|
152 |
+ wd.len = 0; |
|
153 |
+ urlp = NULL; |
|
154 |
+ |
|
155 |
+ |
|
156 |
+ /*** The GET presigned ***/ |
|
157 |
+ if (malware == 1) |
|
158 |
+ curl_easy_setopt(clam_curl, CURLOPT_URL, "http://www.clamav.net/presigned?type=malware"); |
|
159 |
+ else |
|
160 |
+ curl_easy_setopt(clam_curl, CURLOPT_URL, "http://www.clamav.net/presigned?type=fp"); |
|
161 |
+ curl_easy_setopt(clam_curl, CURLOPT_HTTPGET, 1); |
|
162 |
+ len = strlen(hd_malware.cfduid) + strlen(hd_malware.session) + 3; |
|
163 |
+ str = malloc(len); |
|
164 |
+ if (str == NULL) { |
|
165 |
+ fprintf(stderr, "No memory for GET presigned cookies\n"); |
|
166 |
+ exit(1); |
|
121 | 167 |
} |
168 |
+ if (snprintf(str, len, "%s; %s;", hd_malware.cfduid, hd_malware.session) > len) { |
|
169 |
+ fprintf(stderr, "snprintf() failed formatting GET presigned cookies\n"); |
|
170 |
+ exit(1); |
|
171 |
+ } |
|
172 |
+ curl_easy_setopt(clam_curl, CURLOPT_COOKIE, str); |
|
173 |
+ free(str); |
|
174 |
+ len = strlen(authenticity_token) + 15; |
|
175 |
+ str = malloc(len); |
|
176 |
+ if (str == NULL) { |
|
177 |
+ fprintf(stderr, "No memory for GET presigned X-CSRF-Token\n"); |
|
178 |
+ exit(1); |
|
179 |
+ } |
|
180 |
+ if (snprintf(str, len, "X-CSRF-Token: %s", authenticity_token) > len) { |
|
181 |
+ fprintf(stderr, "snprintf() failed for GET presigned X-CSRF-Token\n"); |
|
182 |
+ exit(1); |
|
183 |
+ } |
|
184 |
+ slist = curl_slist_append(slist, str); |
|
185 |
+ free(str); |
|
186 |
+ curl_easy_setopt(clam_curl, CURLOPT_HTTPHEADER, slist); |
|
187 |
+ curl_easy_setopt(clam_curl, CURLOPT_HEADERDATA, &hd_presigned); |
|
188 |
+ curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, header_cb); |
|
189 |
+ if (malware ==1) |
|
190 |
+ curl_easy_setopt(clam_curl, CURLOPT_REFERER, "http://www.clamav.net/reports/malware"); |
|
191 |
+ else |
|
192 |
+ curl_easy_setopt(clam_curl, CURLOPT_REFERER, "http://www.clamav.net/reports/fp"); |
|
193 |
+ |
|
194 |
+ res = curl_easy_perform(clam_curl); |
|
195 |
+ if (res) { |
|
196 |
+ fprintf(stderr, "Error in GET presigned: %s\n", curl_easy_strerror(res)); |
|
197 |
+ exit(1); |
|
198 |
+ } |
|
199 |
+ curl_slist_free_all(slist); |
|
200 |
+ slist = NULL; |
|
122 | 201 |
|
123 |
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "action", CURLFORM_COPYCONTENTS, "submit", CURLFORM_END); |
|
124 |
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "privacy", CURLFORM_COPYCONTENTS, "yes", CURLFORM_END); |
|
125 |
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "notify", CURLFORM_COPYCONTENTS, "yes", CURLFORM_END); |
|
126 | 202 |
|
127 |
- curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); |
|
128 |
- res = curl_easy_perform(curl); |
|
203 |
+ /*** The POST to AWS ***/ |
|
204 |
+ ps_json_obj = json_tokener_parse(wd.str); |
|
205 |
+ if (ps_json_obj == NULL) { |
|
206 |
+ fprintf(stderr, "Error in json_tokener_parse of %.*s\n", wd.len, wd.str); |
|
207 |
+ exit(1); |
|
208 |
+ } |
|
209 |
+ json_str = presigned_get_string(ps_json_obj, "key"); |
|
210 |
+ sp = strchr(json_str, '/'); |
|
211 |
+ if (sp == NULL) { |
|
212 |
+ fprintf(stderr, "Error: malformed 'key' string in GET presigned response (missing '/'.\n"); |
|
213 |
+ exit (1); |
|
214 |
+ } |
|
215 |
+ sp++; |
|
216 |
+ ep = strchr(sp, '-'); |
|
217 |
+ if (ep == NULL) { |
|
218 |
+ fprintf(stderr, "Error: malformed 'key' string in GET presigned response (missing '-'.\n"); |
|
219 |
+ exit (1); |
|
220 |
+ } |
|
221 |
+ submissionID = malloc(ep-sp+1); |
|
222 |
+ if (submissionID == NULL) { |
|
223 |
+ fprintf(stderr, "Error: malloc submissionID.\n"); |
|
224 |
+ exit (1); |
|
225 |
+ } |
|
226 |
+ memcpy(submissionID, sp, ep-sp); |
|
227 |
+ submissionID[ep-sp] = '\0'; |
|
228 |
+ aws_curl = curl_easy_init(); |
|
229 |
+ if (!(aws_curl)) { |
|
230 |
+ fprintf(stderr, "ERROR: Could not initialize libcurl POST presigned\n"); |
|
231 |
+ exit(1); |
|
232 |
+ } |
|
233 |
+ submissionID[ep-sp] = '\0'; |
|
234 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "key", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
|
235 |
+ json_str = presigned_get_string(ps_json_obj, "acl"); |
|
236 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "acl", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
|
237 |
+ json_str = presigned_get_string(ps_json_obj, "policy"); |
|
238 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "policy", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
|
239 |
+ json_str = presigned_get_string(ps_json_obj, "x-amz-meta-original-filename"); |
|
240 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-meta-original-filename", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
|
241 |
+ json_str = presigned_get_string(ps_json_obj, "x-amz-credential"); |
|
242 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-credential", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
|
243 |
+ json_str = presigned_get_string(ps_json_obj, "x-amz-algorithm"); |
|
244 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-algorithm", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
|
245 |
+ json_str = presigned_get_string(ps_json_obj, "x-amz-date"); |
|
246 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-date", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
|
247 |
+ json_str = presigned_get_string(ps_json_obj, "x-amz-signature"); |
|
248 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "x-amz-signature", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); |
|
249 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_FILE, filename, CURLFORM_END); |
|
250 |
+ slist = curl_slist_append(slist, "Expect:"); |
|
251 |
+ curl_easy_setopt(aws_curl, CURLOPT_HTTPHEADER, slist); |
|
252 |
+ curl_easy_setopt(aws_curl, CURLOPT_URL, "http://clamav-site.s3.amazonaws.com/"); |
|
253 |
+ curl_easy_setopt(aws_curl, CURLOPT_HTTPPOST, post); |
|
129 | 254 |
|
255 |
+ res = curl_easy_perform(aws_curl); |
|
130 | 256 |
if (res) { |
131 |
- fprintf(stderr, "Error: %s\n", curl_easy_strerror(res)); |
|
257 |
+ fprintf(stderr, "Error in POST AWS: %s\n", curl_easy_strerror(res)); |
|
258 |
+ exit(1); |
|
132 | 259 |
} |
133 |
- |
|
134 |
-end: |
|
135 |
- curl_easy_cleanup(curl); |
|
260 |
+ curl_slist_free_all(slist); |
|
261 |
+ slist = NULL; |
|
262 |
+ curl_formfree(post); |
|
263 |
+ post = NULL; |
|
264 |
+ last = NULL; |
|
265 |
+ curl_easy_cleanup(aws_curl); |
|
266 |
+ json_object_put(ps_json_obj); |
|
267 |
+ free(wd.str); |
|
268 |
+ wd.str = NULL; |
|
269 |
+ wd.len = 0; |
|
270 |
+ |
|
271 |
+ |
|
272 |
+ /*** The POST submit to clamav.net ***/ |
|
273 |
+ slist = curl_slist_append(slist, "Expect:"); |
|
274 |
+ len = strlen(hd_malware.cfduid) + strlen(hd_presigned.session) + 3; |
|
275 |
+ str = malloc(len); |
|
276 |
+ if (str == NULL) { |
|
277 |
+ fprintf(stderr, "No memory for POST submit cookies.\n"); |
|
278 |
+ exit(1); |
|
279 |
+ } |
|
280 |
+ if (snprintf(str, len, "%s; %s;", hd_malware.cfduid, hd_presigned.session) > len) { |
|
281 |
+ fprintf(stderr, "snprintf() failed formatting POST submit cookies\n"); |
|
282 |
+ exit(1); |
|
283 |
+ } |
|
284 |
+ curl_easy_setopt(clam_curl, CURLOPT_COOKIE, str); |
|
285 |
+ free(str); |
|
286 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "utf8", CURLFORM_COPYCONTENTS, "\x27" "\x13", CURLFORM_END); |
|
287 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "authenticity_token", CURLFORM_COPYCONTENTS, authenticity_token, CURLFORM_END); |
|
288 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "submissionID", CURLFORM_COPYCONTENTS, submissionID, CURLFORM_END); |
|
289 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "type", CURLFORM_COPYCONTENTS, malware?"malware":"fp", CURLFORM_END); |
|
290 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "sendername", CURLFORM_COPYCONTENTS, name, CURLFORM_END); |
|
291 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "email", CURLFORM_COPYCONTENTS, email, CURLFORM_END); |
|
292 |
+ if (malware == 0) { |
|
293 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "virusname", CURLFORM_COPYCONTENTS, fpvname, CURLFORM_END); |
|
294 |
+ } else { |
|
295 |
+ if (malware == 1) |
|
296 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "shareSample", CURLFORM_COPYCONTENTS, "on", CURLFORM_END); |
|
297 |
+ } |
|
298 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "description", CURLFORM_COPYCONTENTS, "clamsubmit", CURLFORM_END); |
|
299 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "notify", CURLFORM_COPYCONTENTS, "on", CURLFORM_END); |
|
300 |
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "privacy", CURLFORM_COPYCONTENTS, "on", CURLFORM_END); |
|
301 |
+ curl_easy_setopt(clam_curl, CURLOPT_HTTPHEADER, slist); |
|
302 |
+ curl_easy_setopt(clam_curl, CURLOPT_URL, "http://www.clamav.net/reports/submit"); |
|
303 |
+ curl_easy_setopt(clam_curl, CURLOPT_HTTPPOST, post); |
|
304 |
+ curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, NULL); |
|
305 |
+ res = curl_easy_perform(clam_curl); |
|
306 |
+ if (res) { |
|
307 |
+ fprintf(stderr, "Error in POST submit: %s\n", curl_easy_strerror(res)); |
|
308 |
+ exit(1); |
|
309 |
+ } else { |
|
310 |
+ long response_code; |
|
311 |
+ curl_easy_getinfo(clam_curl, CURLINFO_RESPONSE_CODE, &response_code); |
|
312 |
+ if (response_code/100 == 3) { |
|
313 |
+ curl_easy_getinfo(clam_curl, CURLINFO_REDIRECT_URL, &urlp); |
|
314 |
+ if (urlp == NULL) { |
|
315 |
+ fprintf(stderr, "POST submit Location URL is NULL.\n"); |
|
316 |
+ exit(1); |
|
317 |
+ } |
|
318 |
+ sp = strstr(urlp, "/reports/"); |
|
319 |
+ if (sp == NULL) { |
|
320 |
+ fprintf(stderr, "POST submit Location URL is malformed.\n"); |
|
321 |
+ exit(1); |
|
322 |
+ } |
|
323 |
+ if (!strcmp(sp, "/reports/success")) |
|
324 |
+ fprintf(stdout, "Submission success!\n"); |
|
325 |
+ else if (!strcmp(sp, "/reports/failure")) |
|
326 |
+ fprintf(stdout, "Submission failed\n"); |
|
327 |
+ else |
|
328 |
+ fprintf(stdout, "Unknown submission status %s\n", sp); |
|
329 |
+ } |
|
330 |
+ else |
|
331 |
+ fprintf(stderr, "Unexpected POST submit response code: %li\n", response_code); |
|
332 |
+ } |
|
333 |
+ curl_slist_free_all(slist); |
|
334 |
+ curl_formfree(post); |
|
335 |
+ curl_easy_cleanup(clam_curl); |
|
336 |
+ if (wd.str != NULL) { |
|
337 |
+ free(wd.str); |
|
338 |
+ wd.str = NULL; |
|
339 |
+ wd.len = 0; |
|
340 |
+ } |
|
341 |
+ free(hd_malware.cfduid); |
|
342 |
+ free(hd_malware.session); |
|
343 |
+ free(hd_presigned.cfduid); |
|
344 |
+ free(hd_presigned.session); |
|
345 |
+ free(submissionID); |
|
346 |
+ free(authenticity_token); |
|
136 | 347 |
if (fromStream) { |
137 | 348 |
remove(filename); |
138 | 349 |
free(filename); |
... | ... |
@@ -141,6 +446,7 @@ end: |
141 | 141 |
return 0; |
142 | 142 |
} |
143 | 143 |
|
144 |
+ |
|
144 | 145 |
char *read_stream(void) |
145 | 146 |
{ |
146 | 147 |
char *filename; |
... | ... |
@@ -26,6 +26,9 @@ Required option for setting the name of the sender for the submission. |
26 | 26 |
.TP |
27 | 27 |
\fB-p FILE\fR |
28 | 28 |
Submit a file that reports as a false positive (ClamAV flags the file as virus). FILE can be \- to specify stdin. Mutually exclusive with \-n. |
29 |
+.TP |
|
30 |
+\fB-V VIRUS\fR |
|
31 |
+The name of the virus detected as false positive. This option is required for false positive submissions. |
|
29 | 32 |
.SH "AUTHOR" |
30 | 33 |
.LP |
31 | 34 |
Shawn Webb <swebb@sourcefire.com> |