Merge pull request #31 from zde/master
[platform/upstream/libsolv.git] / ext / repo_rpmdb_pubkey.c
index 3691332..25bc60d 100644 (file)
 #include "chksum.h"
 #include "repo_rpmdb.h"
 
-/* FIXME: dedup with repo_rpmdb.c */
-static void
+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)
-                break;
-              else if ((c & 0x020821f0) == 0x02000000)
-                break;
-              else if ((c & 0x000820f8) == 0x00080000)
-                break;
-              else if ((c & 0x0000207c) == 0x00002000)
-                break;
-            }
-        }
-      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);
+  if (str[solv_validutf8(str)])
+    {    
+      char *ustr = solv_latin1toutf8(str);     /* not utf8, assume latin1 */
+      repodata_set_str(repodata, handle, tag, ustr);
+      solv_free(ustr);
+    }    
+  else 
+    repodata_set_str(repodata, handle, tag, str);
 }
 
 static char *
@@ -251,9 +188,9 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
   int x, tag, l;
   unsigned char keyid[8];
   unsigned int kcr = 0, maxex = 0;
+#if 0
   unsigned char *pubkey = 0;
   unsigned char *userid = 0;
-#if 0
   int pubkeyl = 0;
   int useridl = 0;
 #endif
@@ -312,14 +249,14 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
        return;
       if (tag == 6)
        {
+#if 0
          pubkey = solv_realloc(pubkey, l);
          if (l)
            memcpy(pubkey, p, l);
-#if 0
          pubkeyl = l;
 #endif
          kcr = 0;
-         if (p[0] == 3)
+         if (p[0] == 3 && l >= 10)
            {
              unsigned int ex;
              void *h;
@@ -334,25 +271,32 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
              memset(keyid, 0, 8);
              if (p[7] == 1)    /* RSA */
                {
-                 int i, ql;
+                 int i, ql, ql2;
                  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);
+                 ql = ((p[8] << 8 | p[9]) + 7) / 8;    /* length of public modulus */
+                 if (ql >= 8 && 10 + ql + 2 <= l)
+                   {
+                     memcpy(keyid, p + 10 + ql - 8, 8);        /* keyid is last 64 bits of public modulus */
+                     q = p + 10 + ql;
+                     ql2 = ((q[0] << 8 | q[1]) + 7) / 8;       /* length of encryption exponent */
+                     if (10 + ql + 2 + ql2 <= l)
+                       {
+                         /* fingerprint is the md5 over the two MPI bodies */
+                         h = solv_chksum_create(REPOKEY_TYPE_MD5);
+                         solv_chksum_add(h, p + 10, ql);
+                         solv_chksum_add(h, q + 2, ql2);
+                         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)
+         else if (p[0] == 4 && l >= 6)
            {
              int i;
              void *h;
@@ -364,6 +308,7 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
              hdr[0] = 0x99;
              hdr[1] = l >> 8;
              hdr[2] = l;
+             /* fingerprint is the sha1 over the packet */
              h = solv_chksum_create(REPOKEY_TYPE_SHA1);
              solv_chksum_add(h, hdr, 3);
              solv_chksum_add(h, p, l);
@@ -371,7 +316,7 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
              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);
+             memcpy(keyid, fp + 12, 8);        /* keyid is last 64 bits of fingerprint */
            }
        }
       if (tag == 2)
@@ -454,6 +399,7 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
                  while (ql)
                    {
                      int sl;
+                     /* decode sub-packet length */
                      x = *q++;
                      ql--;
                      if (x < 192)
@@ -560,20 +506,22 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
                }
            }
        }
+#if 0
       if (tag == 13)
        {
          userid = solv_realloc(userid, l);
          if (l)
            memcpy(userid, p, l);
-#if 0
          useridl = l;
-#endif
        }
+#endif
     }
   if (maxex)
     repodata_set_num(data, s - s->repo->pool->solvables, PUBKEY_EXPIRES, maxex);
+#if 0
   solv_free(pubkey);
   solv_free(userid);
+#endif
 }
 
 /* this is private to rpm, but rpm lacks an interface to retrieve