clamsubmit/clamsubmit.c
f3107383
 #include <stdio.h>
2682e7dd
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 
 #include <curl/curl.h>
 
 #include "libclamav/clamav.h"
 #include "libclamav/others.h"
2f91ff37
 #include "shared/misc.h"
76cab989
 #include "shared/getopt.h"
2682e7dd
 
2f91ff37
 #define OPTS "e:p:n:N:H:h?v"
542d8518
 
a7cba048
 char *read_stream(void);
6df13d04
 void usage(char *name);
 void version(void);
a7cba048
 
2682e7dd
 void usage(char *name)
 {
7dfd039c
     fprintf(stderr, "USAGE: %s -hHinp?\n", name);
2682e7dd
     fprintf(stderr, "OPTIONS:\n");
b28c454e
     fprintf(stderr, "    -e [EMAIL]\tYour email address (required)\n");
2682e7dd
     fprintf(stderr, "    -h or -?\tShow the help text\n");
7dfd039c
     fprintf(stderr, "    -n [FILE]\tSubmit a false negative (FN)\n");
b28c454e
     fprintf(stderr, "    -N [NAME]\tYour name (required)\n");
7dfd039c
     fprintf(stderr, "    -p [FILE]\tSubmit a fase positive (FP)\n");
2f91ff37
     fprintf(stderr, "    -v\t\tShow version number and exit\n");
a7cba048
     fprintf(stderr, "You must specify -n or -p. Both are mutually exclusive. Pass in - as the filename for stdin.\n");
2682e7dd
     exit(0);
 }
f3107383
 
2f91ff37
 void version(void)
 {
     print_version(NULL);
     exit(0);
 }
 
f3107383
 int main(int argc, char *argv[])
 {
2682e7dd
     CURL *curl;
     CURLcode res;
     int ch;
     struct curl_httppost *post=NULL, *last=NULL;
     struct curl_slist *slist = NULL;
a7cba048
     char *name=NULL, *email=NULL, *filename=NULL;
     int setURL=0, fromStream=0;
 
     curl_global_init(CURL_GLOBAL_ALL);
 
     curl = curl_easy_init();
     if (!(curl)) {
         fprintf(stderr, "ERROR: Could not initialize libcurl\n");
         exit(1);
     }
2682e7dd
 
542d8518
     while ((ch = my_getopt(argc, argv, OPTS)) > 0) {
b28c454e
         switch (ch) {
2f91ff37
             case 'v':
                 version();
b28c454e
             case 'e':
                 email = optarg;
                 break;
             case 'N':
                 name = optarg;
                 break;
a7cba048
             case 'p':
                 if (setURL)
                     usage(argv[0]);
 
                 filename = optarg;
 
                 curl_easy_setopt(curl, CURLOPT_URL, "http://cgi.clamav.net/sendfp.cgi");
                 setURL=1;
                 break;
             case 'n':
                 if (setURL)
                     usage(argv[0]);
 
                 filename = optarg;
 
                 curl_easy_setopt(curl, CURLOPT_URL, "http://cgi.clamav.net/sendmalware.cgi");
                 setURL=1;
                 break;
b28c454e
             case 'h':
             case '?':
a7cba048
             default:
b28c454e
                 usage(argv[0]);
         }
2682e7dd
     }
 
a7cba048
     if (!(name) || !(email) || !(filename))
b28c454e
         usage(argv[0]);
 
a7cba048
     if (strlen(filename) == 1 && filename[0] == '-') {
         filename = read_stream();
         if (!(filename)) {
             fprintf(stderr, "ERROR: Unable to read stream\n");
             exit(1);
         }
2682e7dd
 
a7cba048
         fromStream=1;
     }
2682e7dd
 
     slist = curl_slist_append(slist, "Expect:");
     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
 
a7cba048
     if (curl_formadd(&post, &last, CURLFORM_COPYNAME, "sendername", CURLFORM_COPYCONTENTS, name, CURLFORM_END)) {
         fprintf(stderr, "Unable to specify name in libcurl form for file %s\n", optarg);
         goto end;
     }
542d8518
 
a7cba048
     if (curl_formadd(&post, &last, CURLFORM_COPYNAME, "email", CURLFORM_COPYCONTENTS, email, CURLFORM_END)) {
         fprintf(stderr, "Unable to specify email in libcurl form for file %s\n", optarg);
         goto end;
     }
2682e7dd
 
a7cba048
     if (curl_formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_FILE, filename, CURLFORM_END)) {
         fprintf(stderr, "Unable to specify file path in libcurl form for file %s\n", optarg);
         goto end;
     }
2682e7dd
 
a7cba048
     curl_formadd(&post, &last, CURLFORM_COPYNAME, "action", CURLFORM_COPYCONTENTS, "submit", CURLFORM_END);
     curl_formadd(&post, &last, CURLFORM_COPYNAME, "privacy", CURLFORM_COPYCONTENTS, "yes", CURLFORM_END);
     curl_formadd(&post, &last, CURLFORM_COPYNAME, "notify", CURLFORM_COPYCONTENTS, "yes", CURLFORM_END);
2682e7dd
 
a7cba048
     curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
     res = curl_easy_perform(curl);
2682e7dd
 
a7cba048
     if (res) {
         fprintf(stderr, "Error: %s\n", curl_easy_strerror(res));
     }
2682e7dd
 
a7cba048
 end:
     curl_easy_cleanup(curl);
     if (fromStream) {
         remove(filename);
         free(filename);
     }
b28c454e
 
a7cba048
     return 0;
 }
2682e7dd
 
a7cba048
 char *read_stream(void)
 {
     char *filename;
     char buf[512];
     size_t nread, nwritten;
     FILE *fp;
 
     filename = cli_gentemp(NULL);
     if (!(filename)) {
         return NULL;
     }
 
     fp = fopen(filename, "w");
     if (!(fp)) {
         free(filename);
         return NULL;
     }
 
     while (!feof(stdin)) {
         nwritten = 0;
         nread = fread(buf, 1, sizeof(buf), stdin);
         if (nread == 0) {
             fclose(fp);
             remove(filename);
             free(filename);
             return NULL;
         }
 
         while (nwritten < nread) {
             size_t i;
             i = fwrite(buf, 1, nread, fp);
             if (i == 0) {
                 fclose(fp);
                 remove(filename);
                 free(filename);
                 return NULL;
             }
 
             nwritten += i;
2682e7dd
         }
     }
 
a7cba048
     fclose(fp);
2682e7dd
 
a7cba048
     return filename;
f3107383
 }