opkg: initial implementation of package list signature verification
[oweals/opkg-lede.git] / opkg_download.c
index e8bfce075946fcfd3de4ddca04caab5ab43aaa1f..63702508fd99413397a34070a1c63105f83a1822 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include <curl/curl.h>
+#include <gpgme.h>
 
 #include "opkg.h"
 #include "opkg_download.h"
@@ -34,19 +35,27 @@ opkg_download_progress_callback opkg_cb_download_progress = NULL;
 #endif
 
 int
-curl_progress_func (void* data,
-                         double t, /* dltotal */
-                         double d, /* dlnow */
-                         double ultotal,
-                         double ulnow)
+curl_progress_func (char* url,
+                   double t, /* dltotal */
+                   double d, /* dlnow */
+                   double ultotal,
+                   double ulnow)
 {
     int i;
     int p = d*100/t;
 
-#ifdef LIBOPKG
+#ifdef OPKG_LIB
     if (opkg_cb_download_progress)
     {
-       opkg_cb_download_progress (p);
+       static int prev = -1;
+
+       /* don't report the same percentage multiple times
+        * (this can occur due to rounding) */
+       if (prev == p)
+           return 0;
+       prev = p;
+
+       opkg_cb_download_progress (p, url);
        return 0;
     }
 #endif
@@ -71,7 +80,6 @@ int opkg_download(opkg_conf_t *conf, const char *src, const char *dest_file_name
     char *src_basec = strdup(src);
     char *src_base = basename(src_basec);
     char *tmp_file_location;
-    char *cmd;
 
     opkg_message(conf,OPKG_NOTICE,"Downloading %s\n", src);
        
@@ -142,8 +150,10 @@ int opkg_download(opkg_conf_t *conf, const char *src, const char *dest_file_name
     {
        curl_easy_setopt (curl, CURLOPT_URL, src);
        curl_easy_setopt (curl, CURLOPT_WRITEDATA, file);
-       curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
+       curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0);
+       curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, src);
        curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, curl_progress_func);
+       curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1);
        if (conf->http_proxy || conf->ftp_proxy)
        {
            char *userpwd;
@@ -155,6 +165,8 @@ int opkg_download(opkg_conf_t *conf, const char *src, const char *dest_file_name
        res = curl_easy_perform (curl);
        curl_easy_cleanup (curl);
        fclose (file);
+       if (res)
+           return res;
 
     }
     else
@@ -236,7 +248,7 @@ int opkg_prepare_url_for_install(opkg_conf_t *conf, const char *url, char **name
          if (err)
               return err;
          pkg->local_filename = strdup(url);
-         opkg_message(conf, OPKG_DEBUG2, "Package %s provided by hand \(%s\).\n", pkg->name,pkg->local_filename);
+         opkg_message(conf, OPKG_DEBUG2, "Package %s provided by hand (%s).\n", pkg->name,pkg->local_filename);
           pkg->provided_by_hand = 1;
 
      } else {
@@ -263,3 +275,47 @@ int opkg_prepare_url_for_install(opkg_conf_t *conf, const char *url, char **name
      }
      return 0;
 }
+
+int
+opkg_verify_file (char *text_file, char *sig_file)
+{
+    int status = -1;
+    gpgme_ctx_t ctx;
+    gpgme_data_t sig, text;
+    gpgme_error_t err = -1;
+    gpgme_verify_result_t result;
+    gpgme_signature_t s;
+    
+    err = gpgme_new (&ctx);
+
+    if (err)
+       return -1;
+
+    err = gpgme_data_new_from_file (&sig, sig_file, 1); 
+    if (err)
+       return -1;
+
+    err = gpgme_data_new_from_file (&text, text_file, 1); 
+    if (err)
+       return -1;
+
+    err = gpgme_op_verify (ctx, sig, text, NULL);
+
+    result = gpgme_op_verify_result (ctx);
+
+    /* see if any of the signitures matched */
+    s = result->signatures;
+    while (s)
+    {
+       status = gpg_err_code (s->status);
+       if (status == GPG_ERR_NO_ERROR)
+           break;
+       s = s->next;
+    }
+
+    gpgme_data_release (sig);
+    gpgme_data_release (text);
+    gpgme_release (ctx);
+
+    return status;
+}