#include <curl/curl.h>
#include <json.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
#include <pakfire/downloader.h>
#include <pakfire/i18n.h>
char tempfile[PATH_MAX];
FILE* f;
+ // Crypto Stuff
+ EVP_MD_CTX* evp;
+ const EVP_MD* md;
+ unsigned char computed_digest[EVP_MAX_MD_SIZE];
+ unsigned int computed_digest_length;
+
// Mirrors
char baseurl[PATH_MAX];
struct pakfire_mirrorlist* mirrors;
if (transfer->f)
fclose(transfer->f);
+ // Free OpenSSL EVP context
+ if (transfer->evp)
+ EVP_MD_CTX_free(transfer->evp);
+
if (transfer->mirrors)
pakfire_mirrorlist_unref(transfer->mirrors);
// Copy flags
transfer->flags = flags;
+ // Set message digest
+ transfer->md = EVP_sha512();
+
// Allocate handle
transfer->handle = curl_easy_init();
if (!transfer->handle)
DEBUG(downloader->pakfire, "cURL transfer done: %d - %s\n",
code, curl_easy_strerror(code));
+ // Finish message digest computation
+ if (transfer->evp) {
+ r = EVP_DigestFinal_ex(transfer->evp, transfer->computed_digest, &transfer->computed_digest_length);
+ if (r != 1) {
+ ERROR(downloader->pakfire, "Could not finish message digest computation: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ return 1;
+ }
+ }
+
// Protocol
curl_easy_getinfo(h, CURLINFO_PROTOCOL, &protocol);
if (speed)
DEBUG(downloader->pakfire, " Download Speed: %ld bps\n", speed);
+ // Message Digest
+ char* hexdigest = __pakfire_hexlify(transfer->computed_digest, transfer->computed_digest_length);
+ if (hexdigest) {
+ DEBUG(downloader->pakfire, " Message Digest: %s\n", hexdigest);
+ free(hexdigest);
+ }
+
+ // XXX check if digest matches
+
switch (protocol) {
case CURLPROTO_FILE:
// Handle any errors
static size_t pakfire_downloader_write(char* data, size_t size, size_t nmemb, void* userdata) {
struct pakfire_transfer* transfer = (struct pakfire_transfer*)userdata;
+ int r;
// Do not write empty blocks
- if (!size)
- return size;
+ if (!nmemb)
+ return nmemb;
+
+ // Update message digest
+ if (transfer->evp) {
+ r = EVP_DigestUpdate(transfer->evp, data, nmemb);
+ if (r != 1) {
+ //ERROR(downloader->pakfire, "EVP_DigestUpdate failed: %s\n",
+ // ERR_error_string(ERR_get_error(), NULL));
+ return 0;
+ }
+ }
// Write everything to the allocated file descriptor
return fwrite(data, size, nmemb, transfer->f);
static int pakfire_downloader_prepare_transfer(struct pakfire_downloader* downloader,
struct pakfire_transfer* transfer) {
+ int r;
+
// Increment tries
transfer->tries++;
}
}
+ // Drop any previously used EVP contexts
+ if (transfer->evp) {
+ EVP_MD_CTX_free(transfer->evp);
+ transfer->evp = NULL;
+ }
+
+ // Create a new EVP context
+ if (transfer->md) {
+ transfer->evp = EVP_MD_CTX_new();
+ if (!transfer->evp) {
+ ERROR(downloader->pakfire, "Could not create EVP context: %m\n");
+ return 1;
+ }
+
+ // Initialize the EVP context
+ r = EVP_DigestInit_ex(transfer->evp, transfer->md, NULL);
+ if (r != 1) {
+ ERROR(downloader->pakfire, "Could not initialize EVP context: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ return 1;
+ }
+ }
+
// Write all data to the callback function
curl_easy_setopt(transfer->handle, CURLOPT_WRITEFUNCTION, pakfire_downloader_write);
curl_easy_setopt(transfer->handle, CURLOPT_WRITEDATA, transfer);