The signatures of databases will be verified when the database
is being updated. The option VerifySig in the database section
of pacman.conf will dictate how to deal with the signature.
If there is a need to verify (VerifySig is Always or Optional),
the signature will be downloaded and verifyed.

When signing packages, the signature will come from the database
repository where it belongs. So, if a package will be installed from
core, the signature will be read from the desc file, field %PGPSIG%.

Signed-off-by: Denis A. Altoé Falqueto <[email protected]>
---
 lib/libalpm/be_files.c |   84 +++++++++++++++++++++++++++++++++++++++++++++--
 lib/libalpm/sync.c     |    2 +-
 2 files changed, 81 insertions(+), 5 deletions(-)

diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c
index 97c5c4b..505560f 100644
--- a/lib/libalpm/be_files.c
+++ b/lib/libalpm/be_files.c
@@ -49,6 +49,9 @@
 #include "delta.h"
 #include "deps.h"
 #include "dload.h"
+#include "signing.h"
+
+#define DBSIGEXT ".sig"
 
 
 static int checkdbdir(pmdb_t *db)
@@ -241,6 +244,55 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
        sprintf(syncpath, "%s%s", dbpath, "sync/");
 
        ret = _alpm_download_single_file(dbfile, db->servers, syncpath, force);
+       /* Check the signature of the database, if it is marked as signed */
+       if(db->pgp_verify != PM_PGP_VERIFY_NEVER) {
+               char *dbsigfile = NULL;
+
+               /* Assemble the signature file name */
+               len = strlen(dbfile) + strlen(DBSIGEXT) + 1;
+               MALLOC(dbsigfile, len, RET_ERR(PM_ERR_MEMORY, -1));
+               sprintf(dbsigfile, "%s" DBSIGEXT, dbfile);
+
+               /* Try to download the signature file */
+               ret = _alpm_download_single_file(dbsigfile, db->servers, 
syncpath, force);
+               if (ret == -1 && db->pgp_verify == PM_PGP_VERIFY_ALWAYS) {
+                       _alpm_log(PM_LOG_DEBUG, "failed to download signature 
for db: %s\n", alpm_strerrorlast());
+                       free(dbfile);
+                       free(dbsigfile);
+                       RET_ERR(PM_ERR_SIG_MISSINGDIR, -1);
+               }
+               else if (ret != -1) {
+                       char *fulldbfile = NULL, *fulldbsigfile = NULL;
+
+                       /* Assemble the full db and signature file names */
+                       MALLOC(fulldbfile, strlen(syncpath) + strlen(dbfile) + 
2, RET_ERR(PM_ERR_MEMORY, -1));
+                       MALLOC(fulldbsigfile, strlen(syncpath) + 
strlen(dbsigfile) + 2, RET_ERR(PM_ERR_MEMORY, -1));
+                       sprintf(fulldbfile, "%s/%s", syncpath, dbfile);
+                       sprintf(fulldbsigfile, "%s/%s", syncpath, dbsigfile);
+
+                       /* Check the signature */
+                       _alpm_log(PM_LOG_DEBUG, "fulldbfile = %s\n", 
fulldbfile);
+                       _alpm_log(PM_LOG_DEBUG, "fulldbsigfile = %s\n", 
fulldbsigfile);
+                       int ret = _alpm_gpgme_checksig_file(fulldbfile, 
fulldbsigfile);
+                       _alpm_log(PM_LOG_DEBUG, "return from 
_alpm_gpgme_checksig_file = %d\n", ret);
+
+                       FREE(fulldbfile);
+                       FREE(fulldbsigfile);
+
+                       /* VerifSig = Always -> we will only accept 0 as a 
correct value
+                        *            (missing or invalid signatures are errors)
+                        * VerifSig = Optional -> we will accept 0 or -1 as 
correct values
+                        *            (missing signature is ok, but if it 
present, it must be valid) */
+                       if((db->pgp_verify == PM_PGP_VERIFY_ALWAYS && ret != 0) 
||
+                                       (db->pgp_verify == 
PM_PGP_VERIFY_OPTIONAL && ret == 1)) {
+                               _alpm_log(PM_LOG_ERROR, "the signature doesn't 
match the repository database.\n");
+                               free(dbfile);
+                               free(dbsigfile);
+                               RET_ERR(PM_ERR_SIG_INVALID, -1);
+                       }
+               }
+               FREE(dbsigfile);
+       }
        free(dbfile);
        free(syncpath);
 
@@ -614,11 +666,35 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t 
inforeq)
                                STRDUP(info->md5sum, _alpm_strtrim(line), goto 
error);
                        } else if(strcmp(line, "%PGPSIG%") == 0) {
                                /* PGPSIG tag only appears in sync repositories,
-                                * not the local one. */
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
+                                * not the local one. The size must not be 
fixed,
+                                * because the key used will affect the final 
size */
+                               alpm_list_t *pgpsiglines = NULL;
+                               int len = 0;
+
+                               /* Create a list of strings to store each line 
of the signature */
+                               while(fgets(line, sline, fp) && 
strlen(_alpm_strtrim(line))) {
+                                       char *linedup;
+                                       STRDUP(linedup, _alpm_strtrim(line), 
goto error);
+                                       pgpsiglines = 
alpm_list_add(pgpsiglines, linedup);
+                                       len += strlen(linedup);
+                               }
+
+                               /* Allocate a buffer to hold the full signature 
*/
+                               MALLOC(info->pgpsig.encdata, (size_t)(len + 1), 
goto error);
+                               info->pgpsig.encdata[0] = '\0';
+
+                               /* Assemble the signature from the list of 
strings */
+                               while (pgpsiglines != NULL) {
+                                       alpm_list_t *pgpsig_line = pgpsiglines;
+                                       pgpsiglines = pgpsiglines->next;
+
+                                       strcat(info->pgpsig.encdata, (char 
*)pgpsig_line->data);
+
+                                       /* Free the current node, as it is not 
needed anymore */
+                                       free(pgpsig_line->data);
+                                       free(pgpsig_line);
                                }
-                               STRDUP(info->pgpsig.encdata, 
_alpm_strtrim(line), goto error);
+                               pgpsiglines = NULL;
                        } else if(strcmp(line, "%REPLACES%") == 0) {
                                while(fgets(line, sline, fp) && 
strlen(_alpm_strtrim(line))) {
                                        char *linedup;
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 77afe24..38aa508 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -942,7 +942,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, 
alpm_list_t **data)
                pmdb_t *sdb = alpm_pkg_get_db(spkg);
 
                if(sdb->pgp_verify != PM_PGP_VERIFY_NEVER) {
-                       int ret = _alpm_gpgme_checksig(filepath, pgpsig);
+                       int ret = _alpm_gpgme_checksig_memory(filepath, pgpsig);
                        if((sdb->pgp_verify == PM_PGP_VERIFY_ALWAYS && ret != 
0) ||
                                        (sdb->pgp_verify == 
PM_PGP_VERIFY_OPTIONAL && ret == 1)) {
                                errors++;
-- 
1.7.1.1


Reply via email to