Imported Upstream version 0.6.27
[platform/upstream/libsolv.git] / ext / repo_pubkey.c
index 611708d..eb83839 100644 (file)
@@ -14,8 +14,6 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <limits.h>
-#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -257,6 +255,12 @@ pgphashalgo2type(int algo)
     return REPOKEY_TYPE_SHA1;
   if (algo == 8)
     return REPOKEY_TYPE_SHA256;
+  if (algo == 9)
+    return REPOKEY_TYPE_SHA384;
+  if (algo == 10)
+    return REPOKEY_TYPE_SHA512;
+  if (algo == 11)
+    return REPOKEY_TYPE_SHA224;
   return 0;
 }
 
@@ -264,7 +268,7 @@ pgphashalgo2type(int algo)
  * hash the final trailer
  * create a "sigdata" block suitable for a call to solv_pgpverify */
 static void
-pgpsig_makesigdata(struct pgpsig *sig, unsigned char *p, int l, unsigned char *pubkey, int pubkeyl, unsigned char *userid, int useridl, void *h)
+pgpsig_makesigdata(struct pgpsig *sig, unsigned char *p, int l, unsigned char *pubkey, int pubkeyl, unsigned char *userid, int useridl, Chksum *h)
 {
   int type = sig->type;
   unsigned char b[6];
@@ -502,6 +506,7 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
   unsigned char *pstart = p;
   int tag, l;
   unsigned char keyid[8];
+  char subkeyofstr[17];
   unsigned int kcr = 0, maxex = 0, maxsigcr = 0;
   unsigned char *pubkey = 0;
   int pubkeyl = 0;
@@ -511,6 +516,7 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
   unsigned char *pubdata = 0;
   int pubdatal = 0;
 
+  *subkeyofstr = 0;
   for (; ; p += l, pl -= l)
     {
       int hl = parsepkgheader(p, pl, &tag, &l);
@@ -543,6 +549,8 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
              sprintf(evr + 8, "-%08x", maxsigcr);
              s->evr = pool_str2id(repo->pool, evr, 1);
            }
+         if (insubkey && *subkeyofstr)
+           repodata_set_str(data, s - repo->pool->solvables, PUBKEY_SUBKEYOF, subkeyofstr);
          if (pubdata)          /* set data blob */
            repodata_set_binary(data, s - repo->pool->solvables, PUBKEY_DATA, pubdata, pubdatal);
          if (!pl)
@@ -554,6 +562,8 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
            }
          if (tag == 6 || (tag == 14 && !(flags & ADD_WITH_SUBKEYS)))
            break;
+         if (tag == 14 && pubdata && !insubkey)
+           solv_bin2hex(keyid, 8, subkeyofstr);
          /* create new solvable for subkey */
          s = pool_id2solvable(repo->pool, repo_add_solvable(repo));
        }
@@ -570,10 +580,12 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
            }
          else
            insubkey = 1;
+         pubdata = 0;
+         pubdatal = 0;
          if (p[0] == 3 && l >= 10)
            {
              unsigned int ex;
-             void *h;
+             Chksum *h;
              maxsigcr = kcr = p[1] << 24 | p[2] << 16 | p[3] << 8 | p[4];
              ex = 0;
              if (p[5] || p[6])
@@ -613,7 +625,7 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
            }
          else if (p[0] == 4 && l >= 6)
            {
-             void *h;
+             Chksum *h;
              unsigned char hdr[3];
              unsigned char fp[20];
              char fpx[40 + 1];
@@ -648,7 +660,7 @@ parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
          htype = pgphashalgo2type(sig.hashalgo);
          if (htype && sig.mpioff)
            {
-             void *h = solv_chksum_create(htype);
+             Chksum *h = solv_chksum_create(htype);
              pgpsig_makesigdata(&sig, p, l, pubkey, pubkeyl, userid, useridl, h);
              solv_chksum_free(h, 0);
            }
@@ -1048,7 +1060,7 @@ repo_add_keyring(Repo *repo, FILE *fp, int flags)
 }
 
 int
-repo_add_keydir(Repo *repo, const char *keydir, int flags, const char *suffix)
+repo_add_keydir(Repo *repo, const char *keydir, const char *suffix, int flags)
 {
   Pool *pool = repo->pool;
   Repodata *data;
@@ -1139,10 +1151,8 @@ solvsig_free(Solvsig *ss)
   solv_free(ss);
 }
 
-#ifdef ENABLE_PGPVRFY
-
 static int
-repo_verify_sigdata_cmp(const void *va, const void *vb, void *dp)
+repo_find_all_pubkeys_cmp(const void *va, const void *vb, void *dp)
 {
   Pool *pool = dp;
   Id a = *(Id *)va;
@@ -1151,33 +1161,57 @@ repo_verify_sigdata_cmp(const void *va, const void *vb, void *dp)
   return strcmp(pool_id2str(pool, pool->solvables[b].evr), pool_id2str(pool, pool->solvables[a].evr));
 }
 
-/* warning: does not check key expiry/revokation, like gpgv or rpm */
-/* returns the Id of the pubkey that verified the signature */
-Id
-repo_verify_sigdata(Repo *repo, unsigned char *sigdata, int sigdatal, const char *keyid)
+void
+repo_find_all_pubkeys(Repo *repo, const char *keyid, Queue *q)
 {
   Id p;
   Solvable *s;
-  Queue q;
-  int i;
 
-  if (!sigdata || !keyid)
-    return 0;
-  queue_init(&q);
+  queue_empty(q);
+  if (!keyid)
+    return;
+  queue_init(q);
   FOR_REPO_SOLVABLES(repo, p, s)
     {
-      const char *evr = pool_id2str(s->repo->pool, s->evr);
-      const char *kidstr;
+      const char *kidstr, *evr = pool_id2str(s->repo->pool, s->evr);
 
       if (!evr || strncmp(evr, keyid + 8, 8) != 0)
        continue;
       kidstr = solvable_lookup_str(s, PUBKEY_KEYID);
-      if (!kidstr || strcmp(kidstr, keyid) != 0)
-        continue;
-      queue_push(&q, p);
+      if (kidstr && !strcmp(kidstr, keyid))
+        queue_push(q, p);
     }
-  if (q.count > 1)
-    solv_sort(q.elements, q.count, sizeof(Id), repo_verify_sigdata_cmp, repo->pool);
+  if (q->count > 1)
+    solv_sort(q->elements, q->count, sizeof(Id), repo_find_all_pubkeys_cmp, repo->pool);
+}
+
+Id
+repo_find_pubkey(Repo *repo, const char *keyid)
+{
+  Queue q;
+  Id p;
+  queue_init(&q);
+  repo_find_all_pubkeys(repo, keyid, &q);
+  p = q.count ? q.elements[0] : 0;
+  queue_free(&q);
+  return p;
+}
+
+#ifdef ENABLE_PGPVRFY
+
+/* warning: does not check key expiry/revokation, same as with gpgv or rpm */
+/* returns the Id of the pubkey that verified the signature */
+Id
+repo_verify_sigdata(Repo *repo, unsigned char *sigdata, int sigdatal, const char *keyid)
+{
+  Id p;
+  Queue q;
+  int i;
+
+  if (!sigdata || !keyid)
+    return 0;
+  queue_init(&q);
+  repo_find_all_pubkeys(repo, keyid, &q);
   for (i = 0; i < q.count; i++)
     {
       int pubdatal;
@@ -1191,12 +1225,14 @@ repo_verify_sigdata(Repo *repo, unsigned char *sigdata, int sigdatal, const char
 }
 
 Id
-solvsig_verify(Solvsig *ss, Repo *repo, void *chk)
+solvsig_verify(Solvsig *ss, Repo *repo, Chksum *chk)
 {
   struct pgpsig pgpsig;
   void *chk2;
   Id p;
 
+  if (!chk || solv_chksum_isfinished(chk))
+    return 0;
   pgpsig_init(&pgpsig, ss->sigpkt, ss->sigpktl);
   chk2 = solv_chksum_create_clone(chk);
   pgpsig_makesigdata(&pgpsig, ss->sigpkt, ss->sigpktl, 0, 0, 0, 0, chk2);