]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
split ugly pubkey handling into separate repo_rpmdb_pubkey.c
authorMichael Schroeder <mls@suse.de>
Mon, 15 Apr 2013 15:57:43 +0000 (17:57 +0200)
committerMichael Schroeder <mls@suse.de>
Mon, 15 Apr 2013 15:57:43 +0000 (17:57 +0200)
bindings/solv.i
examples/solv.c
ext/CMakeLists.txt
ext/libsolvext.ver
ext/repo_rpmdb.c
ext/repo_rpmdb.h
ext/repo_rpmdb_pubkey.c [new file with mode: 0644]
ext/repo_rpmdb_pubkey.h [new file with mode: 0644]
tools/rpmdb2solv.c

index 17ec7e6e5cecb49cc9bc890ddba91d94ae576aa1..7901a5b831b1f440807e78a8f94f157c525ba92c 100644 (file)
@@ -419,6 +419,9 @@ typedef int bool;
 #ifdef ENABLE_RPMDB
 #include "repo_rpmdb.h"
 #endif
+#ifdef ENABLE_RPMDB_PUBKEYS
+#include "repo_rpmdb_pubkey.h"
+#endif
 #ifdef ENABLE_DEBIAN
 #include "repo_deb.h"
 #endif
@@ -1425,6 +1428,14 @@ rb_eval_string(
     return repo_add_rpm($self, name, flags);
   }
 #endif
+#ifdef ENABLE_RPMDB_PUBKEYS
+  bool add_rpmdb_pubkeys(int flags = 0) {
+    return repo_add_rpmdb_pubkeys($self, flags);
+  }
+  Id add_pubkey(const char *key, int flags = 0) {
+    return repo_add_pubkey($self, key, flags);
+  }
+#endif
 #ifdef ENABLE_RPMMD
   bool add_rpmmd(FILE *fp, const char *language, int flags = 0) {
     return repo_add_rpmmd($self, fp, language, flags);
index 1fa1dc18054c72cfc3b8712d85d8c55ad39b2d2e..fbe7788105b5bc839a3397a250056650d4c8676e 100644 (file)
@@ -64,6 +64,9 @@
 #include "repo_rpmdb.h"
 #include "pool_fileconflicts.h"
 #endif
+#ifdef ENABLE_RPMDB_PUBKEY
+#include "repo_rpmdb_pubkey.h"
+#endif
 #ifdef ENABLE_DEBIAN
 #include "repo_deb.h"
 #endif
index 025c3dcbc26ee0f5afa1ad20a705254a732fe914..bcd4f8194d9354438eaf921bd4f71c97fd453ab6 100644 (file)
@@ -11,6 +11,13 @@ IF (ENABLE_RPMDB)
         pool_fileconflicts.h repo_rpmdb.h)
 ENDIF (ENABLE_RPMDB)
 
+IF (ENABLE_RPMDB_PUBKEY)
+    SET (libsolvext_SRCS ${libsolvext_SRCS}
+       repo_rpmdb_pubkey.c)
+    SET (libsolvext_HEADERS ${libsolvext_SRCS}
+       repo_rpmdb_pubkey.h)
+ENDIF (ENABLE_RPMDB_PUBKEY)
+
 IF (ENABLE_RPMMD)
     SET (libsolvext_SRCS ${libsolvext_SRCS}
        repo_repomdxml.c repo_rpmmd.c
index 953aadf6c257b43cf4568a0d7836c4a456e86943..98173394089c3669ec6a974f5c326c2360f3bf82 100644 (file)
@@ -33,6 +33,7 @@ SOLV_1.0 {
                rpm_installedrpmdbids;
                rpm_iterate_filelist;
                rpm_query;
+               rpm_query_num;
                rpm_state_create;
                rpm_state_free;
                solv_xfopen;
index 4df577482122f26eeb325521a2dd8497a11ad2e8..e84b8ec71ae17c972a1322b1077d20c99d396dc1 100644 (file)
@@ -2385,6 +2385,14 @@ rpm_query(void *rpmhandle, Id what)
       name = headstring(rpmhead, TAG_NAME);
       r = solv_strdup(name);
       break;
+    case SOLVABLE_SUMMARY:
+      name = headstring(rpmhead, TAG_SUMMARY);
+      r = solv_strdup(name);
+      break;
+    case SOLVABLE_DESCRIPTION:
+      name = headstring(rpmhead, TAG_DESCRIPTION);
+      r = solv_strdup(name);
+      break;
     case SOLVABLE_EVR:
       r = headtoevr(rpmhead);
       break;
@@ -2392,6 +2400,21 @@ rpm_query(void *rpmhandle, Id what)
   return r;
 }
 
+unsigned long long
+rpm_query_num(void *rpmhandle, Id what, unsigned long long notfound)
+{
+  RpmHead *rpmhead = rpmhandle;
+  unsigned int u32;
+
+  switch (what)
+    {
+    case SOLVABLE_INSTALLTIME:
+      u32 = headint32(rpmhead, TAG_INSTALLTIME);
+      return u32 ? u32 : notfound;
+    }
+  return notfound;
+}
+
 int
 rpm_installedrpmdbids(void *rpmstate, const char *index, const char *match, Queue *rpmdbidq)
 {
@@ -2541,645 +2564,3 @@ rpm_byrpmh(void *rpmstate, Header h)
 
 #endif
 
-
-#ifdef ENABLE_RPMDB_PUBKEY
-
-static char *
-r64dec1(char *p, unsigned int *vp, int *eofp)
-{
-  int i, x;
-  unsigned int v = 0;
-
-  for (i = 0; i < 4; )
-    {
-      x = *p++;
-      if (!x)
-       return 0;
-      if (x >= 'A' && x <= 'Z')
-       x -= 'A';
-      else if (x >= 'a' && x <= 'z')
-       x -= 'a' - 26;
-      else if (x >= '0' && x <= '9')
-       x -= '0' - 52;
-      else if (x == '+')
-       x = 62;
-      else if (x == '/')
-       x = 63;
-      else if (x == '=')
-       {
-         x = 0;
-         if (i == 0)
-           {
-             *eofp = 3;
-             *vp = 0;
-             return p - 1;
-           }
-         *eofp += 1;
-       }
-      else
-       continue;
-      v = v << 6 | x;
-      i++;
-    }
-  *vp = v;
-  return p;
-}
-
-static unsigned int
-crc24(unsigned char *p, int len)
-{
-  unsigned int crc = 0xb704ceL;
-  int i;
-
-  while (len--)
-    {
-      crc ^= (*p++) << 16;
-      for (i = 0; i < 8; i++)
-        if ((crc <<= 1) & 0x1000000)
-         crc ^= 0x1864cfbL;
-    }
-  return crc & 0xffffffL;
-}
-
-static unsigned char *
-unarmor(char *pubkey, int *pktlp)
-{
-  char *p;
-  int l, eof;
-  unsigned char *buf, *bp;
-  unsigned int v;
-
-  *pktlp = 0;
-  while (strncmp(pubkey, "-----BEGIN PGP PUBLIC KEY BLOCK-----", 36) != 0)
-    {
-      pubkey = strchr(pubkey, '\n');
-      if (!pubkey)
-       return 0;
-      pubkey++;
-    }
-  pubkey = strchr(pubkey, '\n');
-  if (!pubkey++)
-    return 0;
-  /* skip header lines */
-  for (;;)
-    {
-      while (*pubkey == ' ' || *pubkey == '\t')
-       pubkey++;
-      if (*pubkey == '\n')
-       break;
-      pubkey = strchr(pubkey, '\n');
-      if (!pubkey++)
-       return 0;
-    }
-  pubkey++;
-  p = strchr(pubkey, '=');
-  if (!p)
-    return 0;
-  l = p - pubkey;
-  bp = buf = solv_malloc(l * 3 / 4 + 4);
-  eof = 0;
-  while (!eof)
-    {
-      pubkey = r64dec1(pubkey, &v, &eof);
-      if (!pubkey)
-       {
-         solv_free(buf);
-         return 0;
-       }
-      *bp++ = v >> 16;
-      *bp++ = v >> 8;
-      *bp++ = v;
-    }
-  while (*pubkey == ' ' || *pubkey == '\t' || *pubkey == '\n' || *pubkey == '\r')
-    pubkey++;
-  bp -= eof;
-  if (*pubkey != '=' || (pubkey = r64dec1(pubkey + 1, &v, &eof)) == 0)
-    {
-      solv_free(buf);
-      return 0;
-    }
-  if (v != crc24(buf, bp - buf))
-    {
-      solv_free(buf);
-      return 0;
-    }
-  while (*pubkey == ' ' || *pubkey == '\t' || *pubkey == '\n' || *pubkey == '\r')
-    pubkey++;
-  if (strncmp(pubkey, "-----END PGP PUBLIC KEY BLOCK-----", 34) != 0)
-    {
-      solv_free(buf);
-      return 0;
-    }
-  *pktlp = bp - buf;
-  return buf;
-}
-
-static void
-parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
-{
-  int x, tag, l;
-  unsigned char keyid[8];
-  unsigned int kcr = 0, maxex = 0;
-  unsigned char *pubkey = 0;
-  unsigned char *userid = 0;
-#if 0
-  int pubkeyl = 0;
-  int useridl = 0;
-#endif
-
-  for (; pl; p += l, pl -= l)
-    {
-      x = *p++;
-      pl--;
-      if (!(x & 128) || pl <= 0)
-       return;
-      if ((x & 64) == 0)
-       {
-         /* old format */
-         tag = (x & 0x3c) >> 2;
-         x &= 3;
-         if (x == 3)
-           return;
-         l = 1 << x;
-         if (pl < l)
-           return;
-         x = 0;
-         while (l--)
-           {
-             x = x << 8 | *p++;
-             pl--;
-           }
-         l = x;
-       }
-      else
-       {
-         tag = (x & 0x3f);
-         x = *p++;
-         pl--;
-         if (x < 192)
-           l = x;
-         else if (x >= 192 && x < 224)
-           {
-             if (pl <= 0)
-               return;
-             l = ((x - 192) << 8) + *p++ + 192;
-             pl--;
-           }
-         else if (x == 255)
-           {
-             /* sanity: p[0] must be zero */
-             if (pl <= 4 || p[0] != 0)
-               return;
-             l = p[1] << 16 | p[2] << 8 | p[3];
-             p += 4;
-             pl -= 4;
-           }
-         else
-           return;
-       }
-      if (pl < l)
-       return;
-      if (tag == 6)
-       {
-         pubkey = solv_realloc(pubkey, l);
-         if (l)
-           memcpy(pubkey, p, l);
-#if 0
-         pubkeyl = l;
-#endif
-         kcr = 0;
-         if (p[0] == 3)
-           {
-             unsigned int ex;
-             void *h;
-             kcr = p[1] << 24 | p[2] << 16 | p[3] << 8 | p[4];
-             ex = 0;
-             if (p[5] || p[6])
-               {
-                 ex = kcr + 24*3600 * (p[5] << 8 | p[6]);
-                 if (ex > maxex)
-                   maxex = ex;
-               }
-             memset(keyid, 0, 8);
-             if (p[7] == 1)    /* RSA */
-               {
-                 int i, ql;
-                 unsigned char fp[16];
-                 char fpx[32 + 1];
-                 unsigned char *q;
-
-                 ql = ((p[8] << 8 | p[9]) + 7) / 8;
-                 memcpy(keyid, p + 10 + ql - 8, 8);
-                 h = solv_chksum_create(REPOKEY_TYPE_MD5);
-                 solv_chksum_add(h, p + 10, ql);
-                 q = p + 10 + ql;
-                 ql = ((q[0] << 8 | q[1]) + 7) / 8;
-                 solv_chksum_add(h, q + 2, ql);
-                 solv_chksum_free(h, fp);
-                 for (i = 0; i < 16; i++)
-                   sprintf(fpx + i * 2, "%02x", fp[i]);
-                 repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_FINGERPRINT, fpx);
-               }
-           }
-         else if (p[0] == 4)
-           {
-             int i;
-             void *h;
-             unsigned char hdr[3];
-             unsigned char fp[20];
-             char fpx[40 + 1];
-
-             kcr = p[1] << 24 | p[2] << 16 | p[3] << 8 | p[4];
-             hdr[0] = 0x99;
-             hdr[1] = l >> 8;
-             hdr[2] = l;
-             h = solv_chksum_create(REPOKEY_TYPE_SHA1);
-             solv_chksum_add(h, hdr, 3);
-             solv_chksum_add(h, p, l);
-             solv_chksum_free(h, fp);
-             for (i = 0; i < 20; i++)
-               sprintf(fpx + i * 2, "%02x", fp[i]);
-             repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_FINGERPRINT, fpx);
-             memcpy(keyid, fp + 12, 8);
-           }
-       }
-      if (tag == 2)
-       {
-         if (p[0] == 3 && p[1] == 5)
-           {
-#if 0
-             Id htype = 0;
-#endif
-             /* printf("V3 signature packet\n"); */
-             if (l < 17)
-               continue;
-             if (p[2] != 0x10 && p[2] != 0x11 && p[2] != 0x12 && p[2] != 0x13 && p[2] != 0x1f)
-               continue;
-             if (!memcmp(keyid, p + 6, 8))
-               {
-                 /* printf("SELF SIG\n"); */
-               }
-             else
-               {
-                 /* printf("OTHER SIG\n"); */
-               }
-#if 0
-             if (p[16] == 1)
-               htype = REPOKEY_TYPE_MD5;
-             else if (p[16] == 2)
-               htype = REPOKEY_TYPE_SHA1;
-             else if (p[16] == 8)
-               htype = REPOKEY_TYPE_SHA256;
-             if (htype)
-               {
-                 void *h = solv_chksum_create(htype);
-                 unsigned char b[3], *cs;
-
-                 b[0] = 0x99;
-                 b[1] = pubkeyl >> 8;
-                 b[2] = pubkeyl;
-                 solv_chksum_add(h, b, 3);
-                 solv_chksum_add(h, pubkey, pubkeyl);
-                 if (p[2] >= 0x10 && p[2] <= 0x13)
-                   solv_chksum_add(h, userid, useridl);
-                 solv_chksum_add(h, p + 2, 5);
-                 cs = solv_chksum_get(h, 0);
-                 solv_chksum_free(h, 0);
-               }
-#endif
-           }
-         if (p[0] == 4)
-           {
-             int j, ql, haveissuer;
-             unsigned char *q;
-             unsigned int ex = 0;
-#if 0
-             unsigned int scr = 0;
-#endif
-             unsigned char issuer[8];
-
-             /* printf("V4 signature packet\n"); */
-             if (l < 6)
-               continue;
-             if (p[1] != 0x10 && p[1] != 0x11 && p[1] != 0x12 && p[1] != 0x13 && p[1] != 0x1f)
-               continue;
-             haveissuer = 0;
-             ex = 0;
-             q = p + 4;
-             for (j = 0; q && j < 2; j++)
-               {
-                 if (q + 2 > p + l)
-                   {
-                     q = 0;
-                     break;
-                   }
-                 ql = q[0] << 8 | q[1];
-                 q += 2;
-                 if (q + ql > p + l)
-                   {
-                     q = 0;
-                     break;
-                   }
-                 while (ql)
-                   {
-                     int sl;
-                     x = *q++;
-                     ql--;
-                     if (x < 192)
-                       sl = x;
-                     else if (x == 255)
-                       {
-                         if (ql < 4 || q[0] != 0)
-                           {
-                             q = 0;
-                             break;
-                           }
-                         sl = q[1] << 16 | q[2] << 8 | q[3];
-                         q += 4;
-                         ql -= 4;
-                       }
-                     else
-                       {
-                         if (ql < 1)
-                           {
-                             q = 0;
-                             break;
-                           }
-                         sl = ((x - 192) << 8) + *q++ + 192;
-                         ql--;
-                       }
-                     if (ql < sl)
-                       {
-                         q = 0;
-                         break;
-                       }
-                     x = q[0] & 127;
-                     /* printf("%d SIGSUB %d %d\n", j, x, sl); */
-                     if (x == 16 && sl == 9 && !haveissuer)
-                       {
-                         memcpy(issuer, q + 1, 8);
-                         haveissuer = 1;
-                       }
-#if 0
-                     if (x == 2 && j == 0)
-                       scr = q[1] << 24 | q[2] << 16 | q[3] << 8 | q[4];
-#endif
-                     if (x == 9 && j == 0)
-                       ex = q[1] << 24 | q[2] << 16 | q[3] << 8 | q[4];
-                     q += sl;
-                     ql -= sl;
-                   }
-               }
-             if (ex)
-               ex += kcr;
-             if (haveissuer)
-               {
-#if 0
-                 Id htype = 0;
-                 if (p[3] == 1)
-                   htype = REPOKEY_TYPE_MD5;
-                 else if (p[3] == 2)
-                   htype = REPOKEY_TYPE_SHA1;
-                 else if (p[3] == 8)
-                   htype = REPOKEY_TYPE_SHA256;
-                 if (htype && pubkeyl)
-                   {
-                     void *h = solv_chksum_create(htype);
-                     unsigned char b[6], *cs;
-                     unsigned int hl;
-
-                     b[0] = 0x99;
-                     b[1] = pubkeyl >> 8;
-                     b[2] = pubkeyl;
-                     solv_chksum_add(h, b, 3);
-                     solv_chksum_add(h, pubkey, pubkeyl);
-                     if (p[1] >= 0x10 && p[1] <= 0x13)
-                       {
-                         b[0] = 0xb4;
-                         b[1] = useridl >> 24;
-                         b[2] = useridl >> 16;
-                         b[3] = useridl >> 8;
-                         b[4] = useridl;
-                         solv_chksum_add(h, b, 5);
-                         solv_chksum_add(h, userid, useridl);
-                       }
-                     hl = 6 + (p[4] << 8 | p[5]);
-                     solv_chksum_add(h, p, hl);
-                     b[0] = 4;
-                     b[1] = 0xff;
-                     b[2] = hl >> 24;
-                     b[3] = hl >> 16;
-                     b[4] = hl >> 8;
-                     b[5] = hl;
-                     solv_chksum_add(h, b, 6);
-                     cs = solv_chksum_get(h, 0);
-                     solv_chksum_free(h, 0);
-                   }
-#endif
-                 if (!memcmp(keyid, issuer, 8))
-                   {
-                     /* printf("SELF SIG cr %d ex %d\n", cr, ex); */
-                     if (ex > maxex)
-                       maxex = ex;
-                   }
-                 else
-                   {
-                     /* printf("OTHER SIG cr %d ex %d\n", cr, ex); */
-                   }
-               }
-           }
-       }
-      if (tag == 13)
-       {
-         userid = solv_realloc(userid, l);
-         if (l)
-           memcpy(userid, p, l);
-#if 0
-         useridl = l;
-#endif
-       }
-    }
-  if (maxex)
-    repodata_set_num(data, s - s->repo->pool->solvables, PUBKEY_EXPIRES, maxex);
-  solv_free(pubkey);
-  solv_free(userid);
-}
-
-/* this is private to rpm, but rpm lacks an interface to retrieve
- * the values. Sigh. */
-struct pgpDigParams_s {
-    const char * userid;
-    const unsigned char * hash;
-#ifndef HAVE_PGPDIGGETPARAMS
-    const char * params[4];
-#endif
-    unsigned char tag;
-    unsigned char version;               /*!< version number. */
-    unsigned char time[4];               /*!< time that the key was created. */
-    unsigned char pubkey_algo;           /*!< public key algorithm. */
-    unsigned char hash_algo;
-    unsigned char sigtype;
-    unsigned char hashlen;
-    unsigned char signhash16[2];
-    unsigned char signid[8];
-    unsigned char saved;
-};
-
-#ifndef HAVE_PGPDIGGETPARAMS
-struct pgpDig_s {
-    struct pgpDigParams_s signature;
-    struct pgpDigParams_s pubkey;
-};
-#endif
-
-static int
-pubkey2solvable(Solvable *s, Repodata *data, char *pubkey)
-{
-  Pool *pool = s->repo->pool;
-  unsigned char *pkts;
-  unsigned int btime;
-  int pktsl, i;
-  pgpDig dig = 0;
-  char keyid[16 + 1];
-  char evrbuf[8 + 1 + 8 + 1];
-  struct pgpDigParams_s *digpubkey;
-
-  pkts = unarmor(pubkey, &pktsl);
-  if (!pkts)
-    return 0;
-  setutf8string(data, s - s->repo->pool->solvables, SOLVABLE_DESCRIPTION, pubkey);
-  parsekeydata(s, data, pkts, pktsl);
-  /* only rpm knows how to do the release calculation, we don't dare
-   * to recreate all the bugs */
-#ifndef RPM5
-  dig = pgpNewDig();
-#else
-  dig = pgpDigNew(RPMVSF_DEFAULT, 0);
-#endif
-  (void) pgpPrtPkts(pkts, pktsl, dig, 0);
-
-#ifdef HAVE_PGPDIGGETPARAMS
-  digpubkey = pgpDigGetParams(dig, PGPTAG_PUBLIC_KEY);
-#else
-  digpubkey = &dig->pubkey;
-#endif
-  btime = digpubkey->time[0] << 24 | digpubkey->time[1] << 16 | digpubkey->time[2] << 8 | digpubkey->signid[3];
-  sprintf(evrbuf, "%02x%02x%02x%02x-%02x%02x%02x%02x", digpubkey->signid[4], digpubkey->signid[5], digpubkey->signid[6], digpubkey->signid[7], digpubkey->time[0], digpubkey->time[1], digpubkey->time[2], digpubkey->time[3]);
-
-  repodata_set_num(data, s - s->repo->pool->solvables, SOLVABLE_BUILDTIME, btime);
-
-  s->name = pool_str2id(pool, "gpg-pubkey", 1);
-  s->evr = pool_str2id(pool, evrbuf, 1);
-  s->arch = 1;
-  for (i = 0; i < 8; i++)
-    sprintf(keyid + 2 * i, "%02x", digpubkey->signid[i]);
-  repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_KEYID, keyid);
-  if (digpubkey->userid)
-    setutf8string(data, s - s->repo->pool->solvables, SOLVABLE_SUMMARY, digpubkey->userid);
-#ifndef RPM5
-  (void)pgpFreeDig(dig);
-#else
-  (void)pgpDigFree(dig);
-#endif
-  solv_free((void *)pkts);
-  return 1;
-}
-
-int
-repo_add_rpmdb_pubkeys(Repo *repo, int flags)
-{
-  Pool *pool = repo->pool;
-  struct rpmdbstate state;
-  struct rpmdbentry *entries;
-  int nentries, i;
-  char *str;
-  unsigned int u32;
-  Repodata *data;
-  Solvable *s;
-  const char *rootdir = 0;
-
-  data = repo_add_repodata(repo, flags);
-  if (flags & REPO_USE_ROOTDIR)
-    rootdir = pool_get_rootdir(pool);
-
-  memset(&state, 0, sizeof(state));
-  state.pool = pool;
-  if (!opendbenv(&state, rootdir))
-    return 0;
-  entries = getinstalledrpmdbids(&state, "Name", "gpg-pubkey", &nentries, 0);
-  for (i = 0 ; i < nentries; i++)
-    {
-      RpmHead *rpmhead = rpm_byrpmdbid(&state, entries[i].rpmdbid);
-      if (!rpmhead)
-       continue;
-      str = headstring(rpmhead, TAG_DESCRIPTION);
-      if (!str)
-       continue;
-      s = pool_id2solvable(pool, repo_add_solvable(repo));
-      pubkey2solvable(s, data, str);
-      u32 = headint32(rpmhead, TAG_INSTALLTIME);
-      if (u32)
-        repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLTIME, u32);
-      if (!repo->rpmdbid)
-       repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id));
-      repo->rpmdbid[s - pool->solvables - repo->start] = entries[i].rpmdbid;
-    }
-  solv_free(entries);
-  freestate(&state);
-  if (!(flags & REPO_NO_INTERNALIZE))
-    repodata_internalize(data);
-  return 0;
-}
-
-Id
-repo_add_pubkey(Repo *repo, const char *key, int flags)
-{
-  Pool *pool = repo->pool;
-  Repodata *data;
-  Solvable *s;
-  char *buf;
-  int bufl, l, ll;
-  FILE *fp;
-
-  data = repo_add_repodata(repo, flags);
-  buf = 0;
-  bufl = 0;
-  if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, key) : key, "r")) == 0)
-    {
-      pool_error(pool, -1, "%s: %s", key, strerror(errno));
-      return 0;
-    }
-  for (l = 0; ;)
-    {
-      if (bufl - l < 4096)
-       {
-         bufl += 4096;
-         buf = solv_realloc(buf, bufl);
-       }
-      ll = fread(buf, 1, bufl - l, fp);
-      if (ll < 0)
-       {
-         fclose(fp);
-         pool_error(pool, -1, "%s: %s", key, strerror(errno));
-         return 0;
-       }
-      if (ll == 0)
-       break;
-      l += ll;
-    }
-  buf[l] = 0;
-  fclose(fp);
-  s = pool_id2solvable(pool, repo_add_solvable(repo));
-  if (!pubkey2solvable(s, data, buf))
-    {
-      repo_free_solvable(repo, s - pool->solvables, 1);
-      solv_free(buf);
-      return 0;
-    }
-  solv_free(buf);
-  if (!(flags & REPO_NO_INTERNALIZE))
-    repodata_internalize(data);
-  return s - pool->solvables;
-}
-
-#endif /* ENABLE_RPMDB_PUBKEY */
index 117da426fa65fbc910b41cbf87033a595981f9ff..a0d8a815af337eb7a88658f6cff9f1662ca95f69 100644 (file)
@@ -12,8 +12,6 @@ struct headerToken_s;
 
 extern int repo_add_rpmdb(Repo *repo, Repo *ref, int flags);
 extern Id repo_add_rpm(Repo *repo, const char *rpm, int flags);
-extern int repo_add_rpmdb_pubkeys(Repo *repo, int flags);
-extern Id repo_add_pubkey(Repo *repo, const char *key, int flags);
 
 #define RPMDB_REPORT_PROGRESS  (1 << 8)
 #define RPM_ADD_WITH_PKGID     (1 << 9)
@@ -54,5 +52,6 @@ struct filelistinfo {
 };
 
 extern char *rpm_query(void *rpmhandle, Id what);
+extern unsigned long long rpm_query_num(void *rpmhandle, Id what, unsigned long long notfound);
 extern void rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, struct filelistinfo *), void *cbdata);
 extern Id   repo_add_rpm_handle(Repo *repo, void *rpmhandle, int flags);
diff --git a/ext/repo_rpmdb_pubkey.c b/ext/repo_rpmdb_pubkey.c
new file mode 100644 (file)
index 0000000..4920650
--- /dev/null
@@ -0,0 +1,755 @@
+/*
+ * Copyright (c) 2007-2013, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+/*
+ * repo_rpmdb_pubkey
+ *
+ * support for pubkeys stored in the rpmdb database
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <rpm/rpmio.h>
+#include <rpm/rpmpgp.h>
+#ifndef RPM5
+#include <rpm/header.h>
+#endif
+#include <rpm/rpmdb.h>
+
+#include "pool.h"
+#include "repo.h"
+#include "hash.h"
+#include "util.h"
+#include "queue.h"
+#include "chksum.h"
+#include "repo_rpmdb.h"
+
+/* FIXME: dedup with repo_rpmdb.c */
+static void
+setutf8string(Repodata *repodata, Id handle, Id tag, const char *str)
+{
+  const unsigned char *cp;
+  int state = 0;
+  int c;
+  unsigned char *buf = 0, *bp;
+
+  /* check if it's already utf8, code taken from screen ;-) */
+  cp = (const unsigned char *)str;
+  while ((c = *cp++) != 0)
+    {
+      if (state)
+       {
+          if ((c & 0xc0) != 0x80)
+            break; /* encoding error */
+          c = (c & 0x3f) | (state << 6);
+          if (!(state & 0x40000000))
+           {
+              /* check for overlong sequences */
+              if ((c & 0x820823e0) == 0x80000000)
+                c = 0xfdffffff;
+              else if ((c & 0x020821f0) == 0x02000000)
+                c = 0xfff7ffff;
+              else if ((c & 0x000820f8) == 0x00080000)
+                c = 0xffffd000;
+              else if ((c & 0x0000207c) == 0x00002000)
+                c = 0xffffff70;
+            }
+        }
+      else
+       {
+          /* new sequence */
+          if (c >= 0xfe)
+            break;
+          else if (c >= 0xfc)
+            c = (c & 0x01) | 0xbffffffc;    /* 5 bytes to follow */
+          else if (c >= 0xf8)
+            c = (c & 0x03) | 0xbfffff00;    /* 4 */
+          else if (c >= 0xf0)
+            c = (c & 0x07) | 0xbfffc000;    /* 3 */
+          else if (c >= 0xe0)
+            c = (c & 0x0f) | 0xbff00000;    /* 2 */
+          else if (c >= 0xc2)
+            c = (c & 0x1f) | 0xfc000000;    /* 1 */
+          else if (c >= 0x80)
+            break;
+        }
+      state = (c & 0x80000000) ? c : 0;
+    }
+  if (c)
+    {
+      /* not utf8, assume latin1 */
+      buf = solv_malloc(2 * strlen(str) + 1);
+      cp = (const unsigned char *)str;
+      str = (char *)buf;
+      bp = buf;
+      while ((c = *cp++) != 0)
+       {
+         if (c >= 0xc0)
+           {
+             *bp++ = 0xc3;
+             c ^= 0x80;
+           }
+         else if (c >= 0x80)
+           *bp++ = 0xc2;
+         *bp++ = c;
+       }
+      *bp++ = 0;
+    }
+  repodata_set_str(repodata, handle, tag, str);
+  if (buf)
+    solv_free(buf);
+}
+
+static char *
+r64dec1(char *p, unsigned int *vp, int *eofp)
+{
+  int i, x;
+  unsigned int v = 0;
+
+  for (i = 0; i < 4; )
+    {
+      x = *p++;
+      if (!x)
+       return 0;
+      if (x >= 'A' && x <= 'Z')
+       x -= 'A';
+      else if (x >= 'a' && x <= 'z')
+       x -= 'a' - 26;
+      else if (x >= '0' && x <= '9')
+       x -= '0' - 52;
+      else if (x == '+')
+       x = 62;
+      else if (x == '/')
+       x = 63;
+      else if (x == '=')
+       {
+         x = 0;
+         if (i == 0)
+           {
+             *eofp = 3;
+             *vp = 0;
+             return p - 1;
+           }
+         *eofp += 1;
+       }
+      else
+       continue;
+      v = v << 6 | x;
+      i++;
+    }
+  *vp = v;
+  return p;
+}
+
+static unsigned int
+crc24(unsigned char *p, int len)
+{
+  unsigned int crc = 0xb704ceL;
+  int i;
+
+  while (len--)
+    {
+      crc ^= (*p++) << 16;
+      for (i = 0; i < 8; i++)
+        if ((crc <<= 1) & 0x1000000)
+         crc ^= 0x1864cfbL;
+    }
+  return crc & 0xffffffL;
+}
+
+static unsigned char *
+unarmor(char *pubkey, int *pktlp)
+{
+  char *p;
+  int l, eof;
+  unsigned char *buf, *bp;
+  unsigned int v;
+
+  *pktlp = 0;
+  while (strncmp(pubkey, "-----BEGIN PGP PUBLIC KEY BLOCK-----", 36) != 0)
+    {
+      pubkey = strchr(pubkey, '\n');
+      if (!pubkey)
+       return 0;
+      pubkey++;
+    }
+  pubkey = strchr(pubkey, '\n');
+  if (!pubkey++)
+    return 0;
+  /* skip header lines */
+  for (;;)
+    {
+      while (*pubkey == ' ' || *pubkey == '\t')
+       pubkey++;
+      if (*pubkey == '\n')
+       break;
+      pubkey = strchr(pubkey, '\n');
+      if (!pubkey++)
+       return 0;
+    }
+  pubkey++;
+  p = strchr(pubkey, '=');
+  if (!p)
+    return 0;
+  l = p - pubkey;
+  bp = buf = solv_malloc(l * 3 / 4 + 4);
+  eof = 0;
+  while (!eof)
+    {
+      pubkey = r64dec1(pubkey, &v, &eof);
+      if (!pubkey)
+       {
+         solv_free(buf);
+         return 0;
+       }
+      *bp++ = v >> 16;
+      *bp++ = v >> 8;
+      *bp++ = v;
+    }
+  while (*pubkey == ' ' || *pubkey == '\t' || *pubkey == '\n' || *pubkey == '\r')
+    pubkey++;
+  bp -= eof;
+  if (*pubkey != '=' || (pubkey = r64dec1(pubkey + 1, &v, &eof)) == 0)
+    {
+      solv_free(buf);
+      return 0;
+    }
+  if (v != crc24(buf, bp - buf))
+    {
+      solv_free(buf);
+      return 0;
+    }
+  while (*pubkey == ' ' || *pubkey == '\t' || *pubkey == '\n' || *pubkey == '\r')
+    pubkey++;
+  if (strncmp(pubkey, "-----END PGP PUBLIC KEY BLOCK-----", 34) != 0)
+    {
+      solv_free(buf);
+      return 0;
+    }
+  *pktlp = bp - buf;
+  return buf;
+}
+
+static void
+parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
+{
+  int x, tag, l;
+  unsigned char keyid[8];
+  unsigned int kcr = 0, maxex = 0;
+  unsigned char *pubkey = 0;
+  unsigned char *userid = 0;
+#if 0
+  int pubkeyl = 0;
+  int useridl = 0;
+#endif
+
+  for (; pl; p += l, pl -= l)
+    {
+      x = *p++;
+      pl--;
+      if (!(x & 128) || pl <= 0)
+       return;
+      if ((x & 64) == 0)
+       {
+         /* old format */
+         tag = (x & 0x3c) >> 2;
+         x &= 3;
+         if (x == 3)
+           return;
+         l = 1 << x;
+         if (pl < l)
+           return;
+         x = 0;
+         while (l--)
+           {
+             x = x << 8 | *p++;
+             pl--;
+           }
+         l = x;
+       }
+      else
+       {
+         tag = (x & 0x3f);
+         x = *p++;
+         pl--;
+         if (x < 192)
+           l = x;
+         else if (x >= 192 && x < 224)
+           {
+             if (pl <= 0)
+               return;
+             l = ((x - 192) << 8) + *p++ + 192;
+             pl--;
+           }
+         else if (x == 255)
+           {
+             /* sanity: p[0] must be zero */
+             if (pl <= 4 || p[0] != 0)
+               return;
+             l = p[1] << 16 | p[2] << 8 | p[3];
+             p += 4;
+             pl -= 4;
+           }
+         else
+           return;
+       }
+      if (pl < l)
+       return;
+      if (tag == 6)
+       {
+         pubkey = solv_realloc(pubkey, l);
+         if (l)
+           memcpy(pubkey, p, l);
+#if 0
+         pubkeyl = l;
+#endif
+         kcr = 0;
+         if (p[0] == 3)
+           {
+             unsigned int ex;
+             void *h;
+             kcr = p[1] << 24 | p[2] << 16 | p[3] << 8 | p[4];
+             ex = 0;
+             if (p[5] || p[6])
+               {
+                 ex = kcr + 24*3600 * (p[5] << 8 | p[6]);
+                 if (ex > maxex)
+                   maxex = ex;
+               }
+             memset(keyid, 0, 8);
+             if (p[7] == 1)    /* RSA */
+               {
+                 int i, ql;
+                 unsigned char fp[16];
+                 char fpx[32 + 1];
+                 unsigned char *q;
+
+                 ql = ((p[8] << 8 | p[9]) + 7) / 8;
+                 memcpy(keyid, p + 10 + ql - 8, 8);
+                 h = solv_chksum_create(REPOKEY_TYPE_MD5);
+                 solv_chksum_add(h, p + 10, ql);
+                 q = p + 10 + ql;
+                 ql = ((q[0] << 8 | q[1]) + 7) / 8;
+                 solv_chksum_add(h, q + 2, ql);
+                 solv_chksum_free(h, fp);
+                 for (i = 0; i < 16; i++)
+                   sprintf(fpx + i * 2, "%02x", fp[i]);
+                 repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_FINGERPRINT, fpx);
+               }
+           }
+         else if (p[0] == 4)
+           {
+             int i;
+             void *h;
+             unsigned char hdr[3];
+             unsigned char fp[20];
+             char fpx[40 + 1];
+
+             kcr = p[1] << 24 | p[2] << 16 | p[3] << 8 | p[4];
+             hdr[0] = 0x99;
+             hdr[1] = l >> 8;
+             hdr[2] = l;
+             h = solv_chksum_create(REPOKEY_TYPE_SHA1);
+             solv_chksum_add(h, hdr, 3);
+             solv_chksum_add(h, p, l);
+             solv_chksum_free(h, fp);
+             for (i = 0; i < 20; i++)
+               sprintf(fpx + i * 2, "%02x", fp[i]);
+             repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_FINGERPRINT, fpx);
+             memcpy(keyid, fp + 12, 8);
+           }
+       }
+      if (tag == 2)
+       {
+         if (p[0] == 3 && p[1] == 5)
+           {
+#if 0
+             Id htype = 0;
+#endif
+             /* printf("V3 signature packet\n"); */
+             if (l < 17)
+               continue;
+             if (p[2] != 0x10 && p[2] != 0x11 && p[2] != 0x12 && p[2] != 0x13 && p[2] != 0x1f)
+               continue;
+             if (!memcmp(keyid, p + 6, 8))
+               {
+                 /* printf("SELF SIG\n"); */
+               }
+             else
+               {
+                 /* printf("OTHER SIG\n"); */
+               }
+#if 0
+             if (p[16] == 1)
+               htype = REPOKEY_TYPE_MD5;
+             else if (p[16] == 2)
+               htype = REPOKEY_TYPE_SHA1;
+             else if (p[16] == 8)
+               htype = REPOKEY_TYPE_SHA256;
+             if (htype)
+               {
+                 void *h = solv_chksum_create(htype);
+                 unsigned char b[3], *cs;
+
+                 b[0] = 0x99;
+                 b[1] = pubkeyl >> 8;
+                 b[2] = pubkeyl;
+                 solv_chksum_add(h, b, 3);
+                 solv_chksum_add(h, pubkey, pubkeyl);
+                 if (p[2] >= 0x10 && p[2] <= 0x13)
+                   solv_chksum_add(h, userid, useridl);
+                 solv_chksum_add(h, p + 2, 5);
+                 cs = solv_chksum_get(h, 0);
+                 solv_chksum_free(h, 0);
+               }
+#endif
+           }
+         if (p[0] == 4)
+           {
+             int j, ql, haveissuer;
+             unsigned char *q;
+             unsigned int ex = 0;
+#if 0
+             unsigned int scr = 0;
+#endif
+             unsigned char issuer[8];
+
+             /* printf("V4 signature packet\n"); */
+             if (l < 6)
+               continue;
+             if (p[1] != 0x10 && p[1] != 0x11 && p[1] != 0x12 && p[1] != 0x13 && p[1] != 0x1f)
+               continue;
+             haveissuer = 0;
+             ex = 0;
+             q = p + 4;
+             for (j = 0; q && j < 2; j++)
+               {
+                 if (q + 2 > p + l)
+                   {
+                     q = 0;
+                     break;
+                   }
+                 ql = q[0] << 8 | q[1];
+                 q += 2;
+                 if (q + ql > p + l)
+                   {
+                     q = 0;
+                     break;
+                   }
+                 while (ql)
+                   {
+                     int sl;
+                     x = *q++;
+                     ql--;
+                     if (x < 192)
+                       sl = x;
+                     else if (x == 255)
+                       {
+                         if (ql < 4 || q[0] != 0)
+                           {
+                             q = 0;
+                             break;
+                           }
+                         sl = q[1] << 16 | q[2] << 8 | q[3];
+                         q += 4;
+                         ql -= 4;
+                       }
+                     else
+                       {
+                         if (ql < 1)
+                           {
+                             q = 0;
+                             break;
+                           }
+                         sl = ((x - 192) << 8) + *q++ + 192;
+                         ql--;
+                       }
+                     if (ql < sl)
+                       {
+                         q = 0;
+                         break;
+                       }
+                     x = q[0] & 127;
+                     /* printf("%d SIGSUB %d %d\n", j, x, sl); */
+                     if (x == 16 && sl == 9 && !haveissuer)
+                       {
+                         memcpy(issuer, q + 1, 8);
+                         haveissuer = 1;
+                       }
+#if 0
+                     if (x == 2 && j == 0)
+                       scr = q[1] << 24 | q[2] << 16 | q[3] << 8 | q[4];
+#endif
+                     if (x == 9 && j == 0)
+                       ex = q[1] << 24 | q[2] << 16 | q[3] << 8 | q[4];
+                     q += sl;
+                     ql -= sl;
+                   }
+               }
+             if (ex)
+               ex += kcr;
+             if (haveissuer)
+               {
+#if 0
+                 Id htype = 0;
+                 if (p[3] == 1)
+                   htype = REPOKEY_TYPE_MD5;
+                 else if (p[3] == 2)
+                   htype = REPOKEY_TYPE_SHA1;
+                 else if (p[3] == 8)
+                   htype = REPOKEY_TYPE_SHA256;
+                 if (htype && pubkeyl)
+                   {
+                     void *h = solv_chksum_create(htype);
+                     unsigned char b[6], *cs;
+                     unsigned int hl;
+
+                     b[0] = 0x99;
+                     b[1] = pubkeyl >> 8;
+                     b[2] = pubkeyl;
+                     solv_chksum_add(h, b, 3);
+                     solv_chksum_add(h, pubkey, pubkeyl);
+                     if (p[1] >= 0x10 && p[1] <= 0x13)
+                       {
+                         b[0] = 0xb4;
+                         b[1] = useridl >> 24;
+                         b[2] = useridl >> 16;
+                         b[3] = useridl >> 8;
+                         b[4] = useridl;
+                         solv_chksum_add(h, b, 5);
+                         solv_chksum_add(h, userid, useridl);
+                       }
+                     hl = 6 + (p[4] << 8 | p[5]);
+                     solv_chksum_add(h, p, hl);
+                     b[0] = 4;
+                     b[1] = 0xff;
+                     b[2] = hl >> 24;
+                     b[3] = hl >> 16;
+                     b[4] = hl >> 8;
+                     b[5] = hl;
+                     solv_chksum_add(h, b, 6);
+                     cs = solv_chksum_get(h, 0);
+                     solv_chksum_free(h, 0);
+                   }
+#endif
+                 if (!memcmp(keyid, issuer, 8))
+                   {
+                     /* printf("SELF SIG cr %d ex %d\n", cr, ex); */
+                     if (ex > maxex)
+                       maxex = ex;
+                   }
+                 else
+                   {
+                     /* printf("OTHER SIG cr %d ex %d\n", cr, ex); */
+                   }
+               }
+           }
+       }
+      if (tag == 13)
+       {
+         userid = solv_realloc(userid, l);
+         if (l)
+           memcpy(userid, p, l);
+#if 0
+         useridl = l;
+#endif
+       }
+    }
+  if (maxex)
+    repodata_set_num(data, s - s->repo->pool->solvables, PUBKEY_EXPIRES, maxex);
+  solv_free(pubkey);
+  solv_free(userid);
+}
+
+/* this is private to rpm, but rpm lacks an interface to retrieve
+ * the values. Sigh. */
+struct pgpDigParams_s {
+    const char * userid;
+    const unsigned char * hash;
+#ifndef HAVE_PGPDIGGETPARAMS
+    const char * params[4];
+#endif
+    unsigned char tag;
+    unsigned char version;               /*!< version number. */
+    unsigned char time[4];               /*!< time that the key was created. */
+    unsigned char pubkey_algo;           /*!< public key algorithm. */
+    unsigned char hash_algo;
+    unsigned char sigtype;
+    unsigned char hashlen;
+    unsigned char signhash16[2];
+    unsigned char signid[8];
+    unsigned char saved;
+};
+
+#ifndef HAVE_PGPDIGGETPARAMS
+struct pgpDig_s {
+    struct pgpDigParams_s signature;
+    struct pgpDigParams_s pubkey;
+};
+#endif
+
+static int
+pubkey2solvable(Solvable *s, Repodata *data, char *pubkey)
+{
+  Pool *pool = s->repo->pool;
+  unsigned char *pkts;
+  unsigned int btime;
+  int pktsl, i;
+  pgpDig dig = 0;
+  char keyid[16 + 1];
+  char evrbuf[8 + 1 + 8 + 1];
+  struct pgpDigParams_s *digpubkey;
+
+  pkts = unarmor(pubkey, &pktsl);
+  if (!pkts)
+    return 0;
+  setutf8string(data, s - s->repo->pool->solvables, SOLVABLE_DESCRIPTION, pubkey);
+  parsekeydata(s, data, pkts, pktsl);
+  /* only rpm knows how to do the release calculation, we don't dare
+   * to recreate all the bugs */
+#ifndef RPM5
+  dig = pgpNewDig();
+#else
+  dig = pgpDigNew(RPMVSF_DEFAULT, 0);
+#endif
+  (void) pgpPrtPkts(pkts, pktsl, dig, 0);
+
+#ifdef HAVE_PGPDIGGETPARAMS
+  digpubkey = pgpDigGetParams(dig, PGPTAG_PUBLIC_KEY);
+#else
+  digpubkey = &dig->pubkey;
+#endif
+  btime = digpubkey->time[0] << 24 | digpubkey->time[1] << 16 | digpubkey->time[2] << 8 | digpubkey->signid[3];
+  sprintf(evrbuf, "%02x%02x%02x%02x-%02x%02x%02x%02x", digpubkey->signid[4], digpubkey->signid[5], digpubkey->signid[6], digpubkey->signid[7], digpubkey->time[0], digpubkey->time[1], digpubkey->time[2], digpubkey->time[3]);
+
+  repodata_set_num(data, s - s->repo->pool->solvables, SOLVABLE_BUILDTIME, btime);
+
+  s->name = pool_str2id(pool, "gpg-pubkey", 1);
+  s->evr = pool_str2id(pool, evrbuf, 1);
+  s->arch = 1;
+  for (i = 0; i < 8; i++)
+    sprintf(keyid + 2 * i, "%02x", digpubkey->signid[i]);
+  repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_KEYID, keyid);
+  if (digpubkey->userid)
+    setutf8string(data, s - s->repo->pool->solvables, SOLVABLE_SUMMARY, digpubkey->userid);
+#ifndef RPM5
+  (void)pgpFreeDig(dig);
+#else
+  (void)pgpDigFree(dig);
+#endif
+  solv_free((void *)pkts);
+  return 1;
+}
+
+int
+repo_add_rpmdb_pubkeys(Repo *repo, int flags)
+{
+  Pool *pool = repo->pool;
+  Queue q;
+  int i;
+  char *str;
+  Repodata *data;
+  Solvable *s;
+  const char *rootdir = 0;
+  void *state;
+
+  data = repo_add_repodata(repo, flags);
+  if (flags & REPO_USE_ROOTDIR)
+    rootdir = pool_get_rootdir(pool);
+  state = rpm_state_create(repo->pool, rootdir);
+  queue_init(&q);
+  rpm_installedrpmdbids(state, "Name", "gpg-pubkey", &q);
+  for (i = 0; i < q.count; i++)
+    {
+      void *handle;
+      unsigned long long itime;
+
+      handle = rpm_byrpmdbid(state, q.elements[i]);
+      if (!handle)
+       continue;
+      str = rpm_query(handle, SOLVABLE_DESCRIPTION);
+      if (!str)
+       continue;
+      s = pool_id2solvable(pool, repo_add_solvable(repo));
+      pubkey2solvable(s, data, str);
+      solv_free(str);
+      itime = rpm_query_num(handle, SOLVABLE_INSTALLTIME, 0);
+      if (itime)
+        repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLTIME, itime);
+      if (!repo->rpmdbid)
+       repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id));
+      repo->rpmdbid[s - pool->solvables - repo->start] = q.elements[i];
+    }
+  queue_free(&q);
+  rpm_state_free(state);
+  if (!(flags & REPO_NO_INTERNALIZE))
+    repodata_internalize(data);
+  return 0;
+}
+
+Id
+repo_add_pubkey(Repo *repo, const char *key, int flags)
+{
+  Pool *pool = repo->pool;
+  Repodata *data;
+  Solvable *s;
+  char *buf;
+  int bufl, l, ll;
+  FILE *fp;
+
+  data = repo_add_repodata(repo, flags);
+  buf = 0;
+  bufl = 0;
+  if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, key) : key, "r")) == 0)
+    {
+      pool_error(pool, -1, "%s: %s", key, strerror(errno));
+      return 0;
+    }
+  for (l = 0; ;)
+    {
+      if (bufl - l < 4096)
+       {
+         bufl += 4096;
+         buf = solv_realloc(buf, bufl);
+       }
+      ll = fread(buf, 1, bufl - l, fp);
+      if (ll < 0)
+       {
+         fclose(fp);
+         pool_error(pool, -1, "%s: %s", key, strerror(errno));
+         return 0;
+       }
+      if (ll == 0)
+       break;
+      l += ll;
+    }
+  buf[l] = 0;
+  fclose(fp);
+  s = pool_id2solvable(pool, repo_add_solvable(repo));
+  if (!pubkey2solvable(s, data, buf))
+    {
+      repo_free_solvable(repo, s - pool->solvables, 1);
+      solv_free(buf);
+      return 0;
+    }
+  solv_free(buf);
+  if (!(flags & REPO_NO_INTERNALIZE))
+    repodata_internalize(data);
+  return s - pool->solvables;
+}
+
diff --git a/ext/repo_rpmdb_pubkey.h b/ext/repo_rpmdb_pubkey.h
new file mode 100644 (file)
index 0000000..a9f9e73
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2013, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#include "repo.h"
+
+extern int repo_add_rpmdb_pubkeys(Repo *repo, int flags);
+extern Id repo_add_pubkey(Repo *repo, const char *key, int flags);
index 0d003312efde7596b6a74817e334f1fd7fbb1906..1a637557c87744201c4062923ea3d5dfbb0566bd 100644 (file)
@@ -25,6 +25,9 @@
 #include "pool.h"
 #include "repo.h"
 #include "repo_rpmdb.h"
+#ifdef ENABLE_RPMDB_PUBKEY
+#include "repo_rpmdb_pubkey.h"
+#endif
 #include "repo_products.h"
 #include "repo_solv.h"
 #include "common_write.h"
@@ -61,12 +64,15 @@ main(int argc, char **argv)
   char *proddir = 0;
 #endif
   char *outfile = 0;
+#ifdef ENABLE_RPMDB_PUBKEY
+  int pubkeys = 0;
+#endif
 
   /*
    * parse arguments
    */
   
-  while ((c = getopt(argc, argv, "Phnxb:r:p:o:")) >= 0)
+  while ((c = getopt(argc, argv, "Phnkxb:r:p:o:")) >= 0)
     switch (c)
       {
       case 'h':
@@ -95,6 +101,12 @@ main(int argc, char **argv)
       case 'o':
         outfile = optarg;
         break;
+#ifdef ENABLE_RPMDB_PUBKEY
+      case 'k':
+        nopacks = 1;
+        pubkeys = 1;
+        break;
+#endif
       default:
        usage(1);
       }
@@ -160,6 +172,16 @@ main(int argc, char **argv)
          exit(1);
        }
     }
+#ifdef ENABLE_RPMDB_PUBKEY
+  if (pubkeys)
+    {
+      if (repo_add_rpmdb_pubkeys(repo, REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE))
+       {
+         fprintf(stderr, "rpmdb2solv: %s\n", pool_errstr(pool));
+         exit(1);
+       }
+    }
+#endif
 
 #ifdef ENABLE_SUSEREPO
   if (proddir && *proddir)