int VtFile_clusters(struct VtFile *file_scan, const char *cluster_date, void (*cb)(json_t *cluster_json, void *data), void *user_data) { CURL *curl; CURLcode res; int ret = 0; json_t *resp_json = NULL; long http_response_code = 0; char url[1024]; if (!cluster_date || !cluster_date[0]) { VT_ERROR("search cluster_date can not be empty\n"); return -1; } VtApiPage_resetBuffer((struct VtApiPage *) file_scan); curl = curl_easy_init(); if (!curl) { VT_ERROR("init curl\n"); goto cleanup; } snprintf(url, sizeof(url) - 1 , VT_API_BASE_URL "file/clusters?apikey=%s&date=%s", file_scan->api_key, cluster_date); // DBG(1, "URL=%s \n", url); curl_easy_setopt(curl, CURLOPT_URL, url); set_std_curl_data(file_scan, curl); /* Perform the request, res will get the return code */ res = curl_easy_perform(curl); DBG(1, "Perform done\n"); /* Check for errors */ if(res != CURLE_OK) { VT_ERROR("curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); ret = res; goto cleanup; } else { curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response_code); if (http_response_code != 200) { VT_ERROR("HTTP Response code: %ld\n", http_response_code); ret = http_response_code; goto cleanup; } } DBG(1, "Page:\n%s\n",file_scan->buffer); if (file_scan->response) VtResponse_put(&file_scan->response); file_scan->response = VtResponse_new(); ret = VtResponse_fromJSONstr(file_scan->response, file_scan->buffer); if (ret) { VT_ERROR("Parsing JSON\n"); goto cleanup; } resp_json = VtResponse_getJanssonObj(file_scan->response); if (resp_json) { json_t *offset_json = json_object_get(resp_json, "offset"); if (json_is_string(offset_json)) { VtFile_setOffset(file_scan, json_string_value(offset_json)); } } if (cb && resp_json) { json_t *clusters_json = json_object_get(resp_json, "clusters"); unsigned int index; json_t *cl_json = NULL; if (!clusters_json || !json_is_array(clusters_json)) { goto cleanup; } json_array_foreach(clusters_json, index, cl_json) { if (!json_is_object(cl_json)) { VT_ERROR("not valid object\n"); continue; } cb(cl_json, user_data); } }
int VtFile_downloadToFile(struct VtFile *file_scan, const char *hash, const char *out_file) { struct DlCallbackData cb_data = { .counter = 0, .fp = NULL }; int ret; DBG(1, "hash=%s out_file=%s\n", hash, out_file); cb_data.fp = fopen(out_file, "w+"); if (!cb_data.fp) { VT_ERROR("Createing output file %s\n", out_file); return -errno; } ret = VtFile_download(file_scan, hash, download_to_file_cb, &cb_data); fclose(cb_data.fp); return ret; } int VtFile_uploadUrl(struct VtFile *file_scan, char **url) { CURL *curl; CURLcode res; int ret = 0; json_t *resp_json = NULL; char get_url[768]; VtApiPage_resetBuffer((struct VtApiPage *) file_scan); curl = curl_easy_init(); if (!curl) { VT_ERROR("init curl\n"); goto cleanup; } ret = snprintf(get_url, sizeof(get_url)-1, VT_API_BASE_URL "file/scan/upload_url?apikey=%s", file_scan->api_key); curl_easy_setopt(curl, CURLOPT_URL, get_url); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // API will redirect set_std_curl_data(file_scan, curl); /* Perform the request, res will get the return code */ res = curl_easy_perform(curl); DBG(1, "Perform done\n"); /* Check for errors */ if(res != CURLE_OK) { VT_ERROR("curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); goto cleanup; } else { } DBG(1, "Page:\n%s\n",file_scan->buffer); if (file_scan->response) VtResponse_put(&file_scan->response); file_scan->response = VtResponse_new(); ret = VtResponse_fromJSONstr(file_scan->response, file_scan->buffer); if (ret) { VT_ERROR("Parsing JSON\n"); goto cleanup; } resp_json = VtResponse_getJanssonObj(file_scan->response); if (resp_json) { json_t *url_json = json_object_get(resp_json, "upload_url"); if (json_is_string(url_json)) { *url = strdup(json_string_value(url_json)); } } cleanup: /* always cleanup */ curl_easy_cleanup(curl); return ret; }
int VtFile_search(struct VtFile *file_scan, const char *query, void (*cb)(const char *resource, void *data), void *user_data) { CURL *curl; CURLcode res; int ret = 0; json_t *resp_json = NULL; struct curl_httppost *formpost=NULL; struct curl_httppost *lastptr=NULL; struct curl_slist *headerlist=NULL; static const char header_buf[] = "Expect:"; long http_response_code = 0; if (!query || !query[0]) { VT_ERROR("search query can not be empty\n"); return -1; } VtApiPage_resetBuffer((struct VtApiPage *) file_scan); curl = curl_easy_init(); if (!curl) { VT_ERROR("init curl\n"); goto cleanup; } // initialize custom header list (stating that Expect: 100-continue is not wanted headerlist = curl_slist_append(headerlist, header_buf); DBG(1, "Api Key = '%s'\n", file_scan->api_key); ret = curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "query", CURLFORM_COPYCONTENTS, query, CURLFORM_END); if (ret) VT_ERROR("Adding qury %s\n", query); ret = curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "apikey", CURLFORM_COPYCONTENTS, file_scan->api_key, CURLFORM_END); if (ret) VT_ERROR("Adding key\n"); if (file_scan->offset) { ret = curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "offset", CURLFORM_COPYCONTENTS, file_scan->offset, CURLFORM_END); if (ret) VT_ERROR("Adding offset\n"); } // DBG(1, "URL=%s \n", url); curl_easy_setopt(curl, CURLOPT_URL, VT_API_BASE_URL "file/search"); set_std_curl_data(file_scan, curl); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); // set form /* Perform the request, res will get the return code */ res = curl_easy_perform(curl); DBG(1, "Perform done\n"); /* Check for errors */ if(res != CURLE_OK) { VT_ERROR("curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); ret = res; goto cleanup; } else { curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response_code); if (http_response_code != 200) { VT_ERROR("HTTP Response code: %ld\n", http_response_code); ret = http_response_code; goto cleanup; } } DBG(1, "Page:\n%s\n",file_scan->buffer); if (file_scan->response) VtResponse_put(&file_scan->response); file_scan->response = VtResponse_new(); ret = VtResponse_fromJSONstr(file_scan->response, file_scan->buffer); if (ret) { VT_ERROR("Parsing JSON\n"); goto cleanup; } resp_json = VtResponse_getJanssonObj(file_scan->response); if (resp_json) { json_t *offset_json = json_object_get(resp_json, "offset"); if (json_is_string(offset_json)) { VtFile_setOffset(file_scan, json_string_value(offset_json)); } } if (cb && resp_json) { json_t *hashes_json = json_object_get(resp_json, "hashes"); unsigned int index; json_t *hash_obj; json_t *offset_json = json_object_get(resp_json, "offset"); if (offset_json && json_is_string(offset_json) && json_string_value(offset_json) && json_string_value(offset_json)[0]) { VtFile_setOffset(file_scan, json_string_value(offset_json)); } if (!hashes_json || !json_is_array(hashes_json)) { VT_ERROR("Parse error: hashes\n"); goto cleanup; } json_array_foreach(hashes_json, index, hash_obj) { if (!json_is_string(hash_obj)) { VT_ERROR("hash is not string\n"); continue; } cb(json_string_value(hash_obj), user_data); } }
int VtUrlDist_parse(struct VtUrlDist* url_dist, void (*cb)(const char *url, unsigned long long timestamp, int total, int positives, json_t *raw_json, void *data), void *user_data) { json_t *resp_json, *url_obj; json_t *url_str_json, *timestamp_json, *total_json, *positives_json; unsigned int index; if (!url_dist || !url_dist->response) { VT_ERROR("No data recieved\n"); return -1; } resp_json = VtResponse_getJanssonObj(url_dist->response); if (!json_is_array(resp_json)) { VT_ERROR("JSON is not array\n"); return -1; } json_array_foreach(resp_json, index, url_obj) { if (!json_is_object(url_obj)) { VT_ERROR("Parse error not a URL object\n"); return -1; } url_str_json = json_object_get(url_obj, "url"); if (!url_str_json || !json_is_string(url_str_json)) { VT_ERROR("Parse error: url string\n"); return -1; } timestamp_json = json_object_get(url_obj, "timestamp"); if (!timestamp_json || !json_is_integer(timestamp_json)) { VT_ERROR("JSON parse error timestamp\n"); return -1; } total_json = json_object_get(url_obj, "total"); if (!total_json || !json_is_integer(total_json)) { VT_ERROR("JSON parse error total\n"); return -1; } positives_json = json_object_get(url_obj, "positives"); if (!positives_json || !json_is_integer(positives_json)) { VT_ERROR("JSON parse error positives\n"); return -1; } // set the after value, so if we do another query, we will not repeat the same data url_dist->after = json_integer_value(timestamp_json); // Call user defined callback function if (cb) cb(json_string_value(url_str_json), json_integer_value(timestamp_json), (int) json_integer_value(total_json), (int) json_integer_value(positives_json), url_obj, user_data); } return 0; }