summaryrefslogtreecommitdiffstats
path: root/pgppubring.c
diff options
context:
space:
mode:
authorThomas Roessler <roessler@does-not-exist.org>1999-01-22 15:24:58 +0000
committerThomas Roessler <roessler@does-not-exist.org>1999-01-22 15:24:58 +0000
commit1b3511a6a1bd35dbaa29b5aba2bac8e4089b3f67 (patch)
tree25faff13721c7017901130514378ae96b19c77fe /pgppubring.c
parent4a933a52f58b27f86dfc4e587d65424d524f60d5 (diff)
Heavy hacking on mutt's pgp support. We no longer read the complete
key ring into memory. For gpg, performance is heavily improved due to the fact that we are passing a couple of key hints to the key ring parsing back-end.
Diffstat (limited to 'pgppubring.c')
-rw-r--r--pgppubring.c1016
1 files changed, 589 insertions, 427 deletions
diff --git a/pgppubring.c b/pgppubring.c
index c093c216..ff878e1b 100644
--- a/pgppubring.c
+++ b/pgppubring.c
@@ -17,7 +17,7 @@
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
* 02139, USA.
- */
+ */
#include <stdio.h>
@@ -36,28 +36,30 @@
static unsigned char *pbuf = NULL;
static size_t plen = 0;
-enum packet_tags {
- PT_RES0 = 0, /* reserved */
- PT_ESK, /* Encrypted Session Key */
- PT_SIG, /* Signature Packet */
- PT_CESK, /* Conventionally Encrypted Session Key Packet */
- PT_OPS, /* One-Pass Signature Packet */
- PT_SECKEY, /* Secret Key Packet */
- PT_PUBKEY, /* Public Key Packet */
- PT_SUBSECKEY, /* Secret Subkey Packet */
- PT_COMPRESSED, /* Compressed Data Packet */
- PT_SKE, /* Symmetrically Encrypted Data Packet */
- PT_MARKER, /* Marker Packet */
- PT_LITERAL, /* Literal Data Packet */
- PT_TRUST, /* Trust Packet */
- PT_NAME, /* Name Packet */
- PT_SUBKEY, /* Subkey Packet */
- PT_RES15, /* Reserved */
- PT_COMMENT /* Comment Packet */
+enum packet_tags
+{
+ PT_RES0 = 0, /* reserved */
+ PT_ESK, /* Encrypted Session Key */
+ PT_SIG, /* Signature Packet */
+ PT_CESK, /* Conventionally Encrypted Session Key Packet */
+ PT_OPS, /* One-Pass Signature Packet */
+ PT_SECKEY, /* Secret Key Packet */
+ PT_PUBKEY, /* Public Key Packet */
+ PT_SUBSECKEY, /* Secret Subkey Packet */
+ PT_COMPRESSED, /* Compressed Data Packet */
+ PT_SKE, /* Symmetrically Encrypted Data Packet */
+ PT_MARKER, /* Marker Packet */
+ PT_LITERAL, /* Literal Data Packet */
+ PT_TRUST, /* Trust Packet */
+ PT_NAME, /* Name Packet */
+ PT_SUBKEY, /* Subkey Packet */
+ PT_RES15, /* Reserved */
+ PT_COMMENT /* Comment Packet */
};
/* FIXME I can't find where those strings are displayed! */
-const char *pgp_packet_name[] = {
+const char *pgp_packet_name[] =
+{
N_("reserved"),
N_("Encrypted Session Key"),
N_("Signature Packet"),
@@ -77,17 +79,24 @@ const char *pgp_packet_name[] = {
N_("Comment Packet")
};
-const char *pgp_pkalgbytype(unsigned char type)
+const char *pgp_pkalgbytype (unsigned char type)
{
- switch(type)
+ switch (type)
{
- case 1: return "RSA";
- case 2: return "RSA";
- case 3: return "RSA";
- case 16: return "ElG";
- case 17: return "DSA";
- case 20: return "ElG";
- default: return "unk";
+ case 1:
+ return "RSA";
+ case 2:
+ return "RSA";
+ case 3:
+ return "RSA";
+ case 16:
+ return "ElG";
+ case 17:
+ return "DSA";
+ case 20:
+ return "ElG";
+ default:
+ return "unk";
}
}
@@ -97,25 +106,36 @@ static struct
char *pkalg;
char *micalg;
}
-pktomic[] =
+pktomic[] =
{
- { "RSA", "pgp-md5" },
- { "ElG", "pgp-rmd160" },
- { "DSA", "pgp-sha1" },
- { NULL, "x-unknown" }
+ {
+ "RSA", "pgp-md5"
+ }
+ ,
+ {
+ "ElG", "pgp-rmd160"
+ }
+ ,
+ {
+ "DSA", "pgp-sha1"
+ }
+ ,
+ {
+ NULL, "x-unknown"
+ }
};
-const char *pgp_pkalg_to_mic(const char *alg)
+const char *pgp_pkalg_to_mic (const char *alg)
{
int i;
-
- for(i = 0; pktomic[i].pkalg; i++)
+
+ for (i = 0; pktomic[i].pkalg; i++)
{
- if(!mutt_strcasecmp(pktomic[i].pkalg, alg))
+ if (!mutt_strcasecmp (pktomic[i].pkalg, alg))
break;
}
-
+
return pktomic[i].micalg;
}
@@ -124,255 +144,349 @@ const char *pgp_pkalg_to_mic(const char *alg)
#if 0
-static const char *hashalgbytype(unsigned char type)
+static const char *hashalgbytype (unsigned char type)
{
- switch(type)
+ switch (type)
{
- case 1: return "MD5";
- case 2: return "SHA1";
- case 3: return "RIPE-MD/160";
- case 4: return "HAVAL";
- default: return "unknown";
+ case 1:
+ return "MD5";
+ case 2:
+ return "SHA1";
+ case 3:
+ return "RIPE-MD/160";
+ case 4:
+ return "HAVAL";
+ default:
+ return "unknown";
}
}
#endif
-short pgp_canencrypt(unsigned char type)
+short pgp_canencrypt (unsigned char type)
{
- switch(type)
+ switch (type)
{
- case 1:
- case 2:
- case 16:
- case 20:
- return 1;
- default:
- return 0;
+ case 1:
+ case 2:
+ case 16:
+ case 20:
+ return 1;
+ default:
+ return 0;
}
}
-short pgp_cansign(unsigned char type)
+short pgp_cansign (unsigned char type)
{
- switch(type)
+ switch (type)
{
- case 1:
- case 3:
- case 16:
- case 17:
- case 20:
- return 1;
- default:
- return 0;
+ case 1:
+ case 3:
+ case 16:
+ case 17:
+ case 20:
+ return 1;
+ default:
+ return 0;
}
}
/* return values:
- *
+
* 1 = sign only
* 2 = encrypt only
* 3 = both
*/
-short pgp_get_abilities(unsigned char type)
+short pgp_get_abilities (unsigned char type)
{
- return (pgp_canencrypt(type) << 1) | pgp_cansign(type);
+ return (pgp_canencrypt (type) << 1) | pgp_cansign (type);
}
-static int read_material(size_t material, size_t *used, FILE *fp)
+static int read_material (size_t material, size_t * used, FILE * fp)
{
- if(*used + material >= plen)
+ if (*used + material >= plen)
{
unsigned char *p;
size_t nplen;
-
+
nplen = *used + material + CHUNKSIZE;
- if(!(p = realloc(pbuf, nplen)))
+ if (!(p = realloc (pbuf, nplen)))
{
- mutt_perror("realloc");
+ mutt_perror ("realloc");
return -1;
}
plen = nplen;
pbuf = p;
}
-
- if(fread(pbuf + *used, 1, material, fp) < material)
+
+ if (fread (pbuf + *used, 1, material, fp) < material)
{
- mutt_perror("fread");
+ mutt_perror ("fread");
return -1;
}
-
+
*used += material;
return 0;
}
-static unsigned char *pgp_read_packet(FILE *fp, size_t *len)
+static unsigned char *pgp_read_packet (FILE * fp, size_t * len)
{
size_t used = 0;
long startpos;
unsigned char ctb;
unsigned char b;
size_t material;
-
- startpos = ftell(fp);
-
- if(!plen)
+
+ startpos = ftell (fp);
+
+ if (!plen)
{
plen = CHUNKSIZE;
- pbuf = safe_malloc(plen);
+ pbuf = safe_malloc (plen);
}
- if(fread(&ctb, 1, 1, fp) < 1)
+ if (fread (&ctb, 1, 1, fp) < 1)
{
- if(!feof(fp))
- mutt_perror("fread");
+ if (!feof (fp))
+ mutt_perror ("fread");
goto bail;
}
- if(!(ctb & 0x80))
+ if (!(ctb & 0x80))
{
goto bail;
}
- if(ctb & 0x40) /* handle PGP 5.0 packets. */
+ if (ctb & 0x40) /* handle PGP 5.0 packets. */
{
int partial = 0;
- pbuf[0] = ctb; used++;
-
- do {
- if(fread(&b, 1, 1, fp) < 1)
+ pbuf[0] = ctb;
+ used++;
+
+ do
+ {
+ if (fread (&b, 1, 1, fp) < 1)
{
- mutt_perror("fread");
+ mutt_perror ("fread");
goto bail;
}
-
- if(b < 192)
+
+ if (b < 192)
{
material = b;
partial = 0;
material -= 1;
- }
- else if(192 <= b && b <= 223)
+ }
+ else if (192 <= b && b <= 223)
{
material = (b - 192) * 256;
- if(fread(&b, 1, 1, fp) < 1)
+ if (fread (&b, 1, 1, fp) < 1)
{
- mutt_perror("fread");
+ mutt_perror ("fread");
goto bail;
}
material += b + 192;
partial = 0;
material -= 2;
}
- else if(b < 255)
+ else if (b < 255)
{
material = 1 << (b & 0x1f);
partial = 1;
material -= 1;
}
- else /* b == 255 */
+ else
+ /* b == 255 */
{
unsigned char buf[4];
- if( fread( buf, 4, 1, fp ) < 1)
+ if (fread (buf, 4, 1, fp) < 1)
{
- mutt_perror("fread");
- goto bail;
+ mutt_perror ("fread");
+ goto bail;
}
- /*assert( sizeof(material) >= 4 );*/
- material = buf[0] << 24;
+ /*assert( sizeof(material) >= 4 ); */
+ material = buf[0] << 24;
material |= buf[1] << 16;
material |= buf[2] << 8;
material |= buf[3];
partial = 0;
material -= 5;
}
-
- if(read_material(material, &used, fp) == -1)
+
+ if (read_material (material, &used, fp) == -1)
goto bail;
- } while (partial);
+ }
+ while (partial);
}
- else /* Old-Style PGP */
+ else
+ /* Old-Style PGP */
{
int bytes = 0;
pbuf[0] = 0x80 | ((ctb >> 2) & 0x0f);
used++;
-
- switch(ctb & 0x03)
+
+ switch (ctb & 0x03)
{
case 0:
{
- if(fread(&b, 1, 1, fp) < 1)
+ if (fread (&b, 1, 1, fp) < 1)
{
- mutt_perror("fread");
+ mutt_perror ("fread");
goto bail;
}
-
+
material = b;
break;
}
-
+
case 1:
- bytes = 2;
-
+ bytes = 2;
+
case 2:
{
int i;
- if(!bytes) bytes = 4;
-
+ if (!bytes)
+ bytes = 4;
+
material = 0;
-
- for(i = 0; i < bytes; i++)
+
+ for (i = 0; i < bytes; i++)
{
- if(fread(&b, 1, 1, fp) < 1)
+ if (fread (&b, 1, 1, fp) < 1)
{
- mutt_perror("fread");
+ mutt_perror ("fread");
goto bail;
}
-
+
material = (material << 8) + b;
}
break;
}
-
+
default:
- goto bail;
+ goto bail;
}
-
- if(read_material(material, &used, fp) == -1)
+
+ if (read_material (material, &used, fp) == -1)
goto bail;
}
-
- if(len)
+
+ if (len)
*len = used;
-
+
return pbuf;
-
- bail:
-
- fseek(fp, startpos, SEEK_SET);
+
+bail:
+
+ fseek (fp, startpos, SEEK_SET);
return NULL;
}
-static KEYINFO *pgp_new_keyinfo(void)
+static pgp_key_t *pgp_new_keyinfo (void)
{
- KEYINFO *p;
+ return safe_calloc (sizeof (pgp_key_t), 1);
+}
- p = safe_malloc(sizeof(KEYINFO));
- p->keyid = NULL;
- p->address = NULL;
- p->flags = 0;
- p->next = NULL;
- p->keylen = 0;
+void pgp_free_uid (pgp_uid_t ** upp)
+{
+ pgp_uid_t *up, *q;
- return p;
+ if (!upp || !*upp)
+ return;
+ for (up = *upp; up; up = q)
+ {
+ q = up->next;
+ safe_free ((void **) &up->addr);
+ safe_free ((void **) &up);
+ }
+
+ *upp = NULL;
+}
+
+static void _pgp_free_key (pgp_key_t ** kpp)
+{
+ pgp_key_t *kp;
+
+ if (!kpp || !*kpp)
+ return;
+
+ kp = *kpp;
+
+ pgp_free_uid (&kp->address);
+ safe_free ((void **) &kp->keyid);
+ safe_free ((void **) kpp);
}
-static KEYINFO *pgp_parse_pgp2_key(unsigned char *buff, size_t l)
+pgp_key_t *pgp_remove_key (pgp_key_t ** klist, pgp_key_t * key)
{
- KEYINFO *p;
+ pgp_key_t **last;
+ pgp_key_t *p, *q, *r;
+
+ if (!klist || !*klist || !key)
+ return NULL;
+
+ if (key->parent && key->parent != key)
+ key = key->parent;
+
+ last = klist;
+ for (p = *klist; p && p != key; p = p->next)
+ last = &p->next;
+
+ if (!p)
+ return NULL;
+
+ for (q = p->next, r = p; q && q->parent == p; q = q->next)
+ r = q;
+
+ if (r)
+ r->next = NULL;
+
+ *last = q;
+ return q;
+}
+
+void pgp_free_key (pgp_key_t ** kpp)
+{
+ pgp_key_t *p, *q, *r;
+
+ if (!kpp || !*kpp)
+ return;
+
+ if ((*kpp)->parent && (*kpp)->parent != *kpp)
+ *kpp = (*kpp)->parent;
+
+ /* Order is important here:
+ *
+ * - First free all children.
+ * - If we are an orphan (i.e., our parent was not in the key list),
+ * free our parent.
+ * - free ourselves.
+ */
+
+ for (p = *kpp; p; p = q)
+ {
+ for (q = p->next; q && q->parent == p; q = r)
+ {
+ r = q->next;
+ _pgp_free_key (&q);
+ }
+ if (p->parent)
+ _pgp_free_key (&p->parent);
+
+ _pgp_free_key (&p);
+ }
+
+ *kpp = NULL;
+}
+
+static pgp_key_t *pgp_parse_pgp2_key (unsigned char *buff, size_t l)
+{
+ pgp_key_t *p;
unsigned char alg;
size_t expl;
unsigned long id;
@@ -381,100 +495,102 @@ static KEYINFO *pgp_parse_pgp2_key(unsigned char *buff, size_t l)
size_t j;
int i, k;
unsigned char scratch[LONG_STRING];
-
- if(l < 12)
+
+ if (l < 12)
return NULL;
-
- p = pgp_new_keyinfo();
-
- for(i = 0, j = 2; i < 4; i++)
+
+ p = pgp_new_keyinfo ();
+
+ for (i = 0, j = 2; i < 4; i++)
gen_time = (gen_time << 8) + buff[j++];
-
- for(i = 0; i < 2; i++)
+
+ for (i = 0; i < 2; i++)
exp_days = (exp_days << 8) + buff[j++];
-
- if(exp_days && time(NULL) > gen_time + exp_days * 24 * 3600)
+
+ if (exp_days && time (NULL) > gen_time + exp_days * 24 * 3600)
p->flags |= KEYFLAG_EXPIRED;
-
+
alg = buff[j++];
-
- p->algorithm = pgp_pkalgbytype(alg);
- p->flags |= pgp_get_abilities(alg);
-
+
+ p->algorithm = pgp_pkalgbytype (alg);
+ p->flags |= pgp_get_abilities (alg);
+
expl = 0;
- for(i = 0; i < 2; i++)
+ for (i = 0; i < 2; i++)
expl = (expl << 8) + buff[j++];
-
+
p->keylen = expl;
-
- expl = (expl + 7)/ 8;
- if(expl < 4)
+
+ expl = (expl + 7) / 8;
+ if (expl < 4)
goto bailout;
-
+
j += expl - 8;
-
- for(k = 0; k < 2; k++)
+
+ for (k = 0; k < 2; k++)
{
- for(id = 0, i = 0; i < 4; i++)
+ for (id = 0, i = 0; i < 4; i++)
id = (id << 8) + buff[j++];
-
- snprintf((char *)scratch + k * 8, sizeof(scratch) - k * 8,
- "%08lX", id);
+
+ snprintf ((char *) scratch + k * 8, sizeof (scratch) - k * 8,
+ "%08lX", id);
}
-
- p->keyid = safe_strdup((char *)scratch);
-
+
+ p->keyid = safe_strdup ((char *) scratch);
+
return p;
-
- bailout:
-
- safe_free((void **)&p);
+
+bailout:
+
+ safe_free ((void **) &p);
return NULL;
}
-static void pgp_make_pgp3_fingerprint(unsigned char *buff, size_t l,
- unsigned char *digest)
+static void pgp_make_pgp3_fingerprint (unsigned char *buff, size_t l,
+ unsigned char *digest)
{
unsigned char dummy;
SHA_CTX context;
- SHA1_Init(&context);
-
+ SHA1_Init (&context);
+
dummy = buff[0] & 0x3f;
- if(dummy == PT_SUBSECKEY || dummy == PT_SUBKEY || dummy == PT_SECKEY)
+ if (dummy == PT_SUBSECKEY || dummy == PT_SUBKEY || dummy == PT_SECKEY)
dummy = PT_PUBKEY;
dummy = (dummy << 2) | 0x81;
- SHA1_Update(&context, &dummy, 1);
+ SHA1_Update (&context, &dummy, 1);
dummy = ((l - 1) >> 8) & 0xff;
- SHA1_Update(&context, &dummy, 1);
- dummy = (l - 1) & 0xff;
- SHA1_Update(&context, &dummy, 1);
- SHA1_Update(&context, buff + 1, l - 1);
- SHA1_Final(digest, &context);
+ SHA1_Update (&context, &dummy, 1);
+ dummy = (l - 1) & 0xff;
+ SHA1_Update (&context, &dummy, 1);
+ SHA1_Update (&context, buff + 1, l - 1);
+ SHA1_Final (digest, &context);
}
-static void skip_bignum(unsigned char *buff, size_t l, size_t j,
- size_t *toff, size_t n)
+static void skip_bignum (unsigned char *buff, size_t l, size_t j,
+ size_t * toff, size_t n)
{
size_t len;
-
+
do
{
- len = (buff[j] << 8) + buff[j+1];
+ len = (buff[j] << 8) + buff[j + 1];
j += (len + 7) / 8 + 2;
- } while(j <= l && --n > 0);
-
- if(toff) *toff = j;
+ }
+ while (j <= l && --n > 0);
+
+ if (toff)
+ *toff = j;
}
-
-static KEYINFO *pgp_parse_pgp3_key(unsigned char *buff, size_t l)
+
+static pgp_key_t *pgp_parse_pgp3_key (unsigned char *buff, size_t l)
{
- KEYINFO *p;
+ pgp_key_t *p;
unsigned char alg;
unsigned char digest[SHA_DIGEST_LENGTH];
unsigned char scratch[LONG_STRING];
@@ -483,98 +599,98 @@ static KEYINFO *pgp_parse_pgp3_key(unsigned char *buff, size_t l)
int i, k;
short len;
size_t j;
-
- p = pgp_new_keyinfo();
+
+ p = pgp_new_keyinfo ();
j = 2;
-
- for(i = 0; i < 4; i++)
+
+ for (i = 0; i < 4; i++)
gen_time = (gen_time << 8) + buff[j++];
p->gen_time = gen_time;
-
+
alg = buff[j++];
-
- p->algorithm = pgp_pkalgbytype(alg);
- p->flags |= pgp_get_abilities(alg);
+
+ p->algorithm = pgp_pkalgbytype (alg);
+ p->flags |= pgp_get_abilities (alg);
if (alg == 17)
- skip_bignum(buff, l, j, &j, 3);
- else if(alg == 16 || alg == 20 )
- skip_bignum(buff, l, j, &j, 2);
-
- len = (buff[j] << 8) + buff[j+1];
+ skip_bignum (buff, l, j, &j, 3);
+ else if (alg == 16 || alg == 20)
+ skip_bignum (buff, l, j, &j, 2);
+
+ len = (buff[j] << 8) + buff[j + 1];
p->keylen = len;
- if (alg >=1 && alg <= 3)
- skip_bignum(buff, l, j, &j, 2);
- else if(alg == 17 || alg == 16)
- skip_bignum(buff, l, j, &j, 1);
-
- pgp_make_pgp3_fingerprint(buff, j, digest);
+ if (alg >= 1 && alg <= 3)
+ skip_bignum (buff, l, j, &j, 2);
+ else if (alg == 17 || alg == 16)
+ skip_bignum (buff, l, j, &j, 1);
+
+ pgp_make_pgp3_fingerprint (buff, j, digest);
- for(k = 0; k < 2; k++)
+ for (k = 0; k < 2; k++)
{
- for(id = 0, i = SHA_DIGEST_LENGTH - 8 + k*4;
- i < SHA_DIGEST_LENGTH + (k - 1) * 4; i++)
+ for (id = 0, i = SHA_DIGEST_LENGTH - 8 + k * 4;
+ i < SHA_DIGEST_LENGTH + (k - 1) * 4; i++)
id = (id << 8) + digest[i];
-
- snprintf((char *)scratch + k * 8, sizeof(scratch) - k * 8, "%08lX", id);
+
+ snprintf ((char *) scratch + k * 8, sizeof (scratch) - k * 8, "%08lX", id);
}
-
- p->keyid = safe_strdup((char *)scratch);
-
+
+ p->keyid = safe_strdup ((char *) scratch);
+
return p;
}
-static KEYINFO *pgp_parse_keyinfo(unsigned char *buff, size_t l)
+static pgp_key_t *pgp_parse_keyinfo (unsigned char *buff, size_t l)
{
- if(!buff || l < 2)
+ if (!buff || l < 2)
return NULL;
dprint (5, (debugfile, " version: %d ", buff[1]));
-
- switch(buff[1])
+
+ switch (buff[1])
{
- case 2:
- case 3:
- return pgp_parse_pgp2_key(buff, l);
- case 4:
- return pgp_parse_pgp3_key(buff, l);
- default:
- return NULL;
+ case 2:
+ case 3:
+ return pgp_parse_pgp2_key (buff, l);
+ case 4:
+ return pgp_parse_pgp3_key (buff, l);
+ default:
+ return NULL;
}
}
-static int pgp_parse_pgp2_sig(unsigned char *buff, size_t l, KEYINFO *p)
+static int pgp_parse_pgp2_sig (unsigned char *buff, size_t l, pgp_key_t * p)
{
unsigned char sigtype;
long sig_gen_time;
unsigned long signerid;
size_t j;
int i;
-
- if(l < 22)
+
+ if (l < 22)
return -1;
-
+
j = 3;
sigtype = buff[j++];
-
+
sig_gen_time = 0;
- for(i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++)
sig_gen_time = (sig_gen_time << 8) + buff[j++];
-
+
j += 4;
signerid = 0;
- for(i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++)
signerid = (signerid << 8) + buff[j++];
-
- if(sigtype == 0x20 || sigtype == 0x28)
+
+ if (sigtype == 0x20 || sigtype == 0x28)
p->flags |= KEYFLAG_REVOKED;
-
+
return 0;
}
-static int pgp_parse_pgp3_sig(unsigned char *buff, size_t l, KEYINFO *p)
+static int pgp_parse_pgp3_sig (unsigned char *buff, size_t l, pgp_key_t * p)
{
unsigned char sigtype;
unsigned char pkalg;
@@ -588,228 +704,226 @@ static int pgp_parse_pgp3_sig(unsigned char *buff, size_t l, KEYINFO *p)
size_t j;
int i;
short ii;
- short have_critical_spks=0;
-
- if(l < 7)
+ short have_critical_spks = 0;
+
+ if (l < 7)
return -1;
-
+
j = 2;
-
+
sigtype = buff[j++];
pkalg = buff[j++];
hashalg = buff[j++];
-
- for(ii = 0; ii < 2; ii++)
+
+ for (ii = 0; ii < 2; ii++)
{
size_t skl;
size_t nextone;
-
- ml = (buff[j] << 8) + buff[j+1];
+
+ ml = (buff[j] << 8) + buff[j + 1];
j += 2;
-
- if(j + ml > l) break;
-
+
+ if (j + ml > l)
+ break;
+
nextone = j;
- while(ml)
+ while (ml)
{
j = nextone;
skl = buff[j++];
- if(!--ml) break;
-
- if(skl >= 192)
+ if (!--ml)
+ break;
+
+ if (skl >= 192)
{
skl = (skl - 192) * 256 + buff[j++] + 192;
- if(!--ml) break;
+ if (!--ml)
+ break;
}
-
- if((int) ml - (int) skl < 0)
+
+ if ((int) ml - (int) skl < 0)
break;
ml -= skl;
-
+
nextone = j + skl;
skt = buff[j++];
-
- switch(skt & 0x7f)
+
+ switch (skt & 0x7f)
{
- case 2: /* creation time */
+ case 2: /* creation time */
{
- if(skl < 4)
+ if (skl < 4)
break;
sig_gen_time = 0;
- for(i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++)
sig_gen_time = (sig_gen_time << 8) + buff[j++];
-
+
break;
}
- case 3: /* expiration time */
+ case 3: /* expiration time */
{
- if(skl < 4)
+ if (skl < 4)
break;
validity = 0;
- for(i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++)
validity = (validity << 8) + buff[j++];
break;
}
- case 9: /* key expiration time */
+ case 9: /* key expiration time */
{
- if(skl < 4)
+ if (skl < 4)
break;
key_validity = 0;
- for(i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++)
key_validity = (key_validity << 8) + buff[j++];
break;
}
- case 16: /* issuer key ID */
+ case 16: /* issuer key ID */
{
- if(skl < 8)
+ if (skl < 8)
break;
j += 4;
signerid = 0;
- for(i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++)
signerid = (signerid << 8) + buff[j++];
break;
}
- case 10: /* CMR key */ break;
- case 4: /* exportable */
- case 5: /* trust */
- case 6: /* regexp */
- case 7: /* revocable */
- case 11: /* Pref. symm. alg. */
- case 12: /* revocation key */
- case 20: /* notation data */
- case 21: /* pref. hash */
- case 22: /* pref. comp.alg. */
- case 23: /* key server prefs. */
- case 24: /* pref. key server */
+ case 10: /* CMR key */
+ break;
+ case 4: /* exportable */
+ case 5: /* trust */
+ case 6: /* regexp */
+ case 7: /* revocable */
+ case 11: /* Pref. symm. alg. */
+ case 12: /* revocation key */
+ case 20: /* notation data */
+ case 21: /* pref. hash */
+ case 22: /* pref. comp.alg. */
+ case 23: /* key server prefs. */
+ case 24: /* pref. key server */
default:
{
- if(skt & 0x80)
+ if (skt & 0x80)
have_critical_spks = 1;
}
}
}
j = nextone;
}
-
- if(sigtype == 0x20 || sigtype == 0x28)
+
+ if (sigtype == 0x20 || sigtype == 0x28)
p->flags |= KEYFLAG_REVOKED;
- if(key_validity != -1 && time(NULL) > p->gen_time + key_validity)
+ if (key_validity != -1 && time (NULL) > p->gen_time + key_validity)
p->flags |= KEYFLAG_EXPIRED;
- if(have_critical_spks)
+ if (have_critical_spks)
p->flags |= KEYFLAG_CRITICAL;
return 0;
-
+
}
-
-static int pgp_parse_sig(unsigned char *buff, size_t l, KEYINFO *p)
+
+static int pgp_parse_sig (unsigned char *buff, size_t l, pgp_key_t * p)
{
- if(!buff || l < 2 || !p)
+ if (!buff || l < 2 || !p)
return -1;
-
- switch(buff[1])
+
+ switch (buff[1])
{
- case 2:
- case 3:
- return pgp_parse_pgp2_sig(buff, l, p);
- case 4:
- return pgp_parse_pgp3_sig(buff, l, p);
- default:
+ case 2:
+ case 3:
+ return pgp_parse_pgp2_sig (buff, l, p);
+ case 4:
+ return pgp_parse_pgp3_sig (buff, l, p);
+ default:
return -1;
}
}
-
-static KEYINFO *pgp_read_keyring(const char *fname)
+/* parse one key block, including all subkeys. */
+
+static pgp_key_t *pgp_parse_keyblock (FILE * fp)
{
- FILE *fp;
unsigned char *buff;
unsigned char pt = 0;
unsigned char last_pt;
size_t l;
- KEYINFO *db = NULL, **end, *p = NULL;
- KEYINFO *supkey = NULL;
- PGPUID *uid = NULL;
- LIST **addr = NULL;
- CHARSET *chs = mutt_get_charset(Charset);
+ short err = 0;
+
+ fpos_t pos;
- if(!(fp = fopen(fname, "r")))
- {
- mutt_perror("fopen");
- return NULL;
-
- }
+ pgp_key_t *root = NULL;
+ pgp_key_t **last = &root;
+ pgp_key_t *p = NULL;
+ pgp_uid_t *uid = NULL;
+ pgp_uid_t **addr = NULL;
+
+ CHARSET *chs = mutt_get_charset (Charset);
- end = &db;
+ fgetpos (fp, &pos);
- while((buff = pgp_read_packet(fp, &l)) != NULL)
+ while (!err && (buff = pgp_read_packet (fp, &l)) != NULL)
{
last_pt = pt;
pt = buff[0] & 0x3f;
- if(l < 1)
- continue;
-
- switch(pt)
+ /* check if we have read the complete key block. */
+
+ if ((pt == PT_SECKEY || pt == PT_PUBKEY) && root)
+ {
+ fsetpos (fp, &pos);
+ return root;
+ }
+
+ switch (pt)
{
case PT_SECKEY:
case PT_PUBKEY:
case PT_SUBKEY:
case PT_SUBSECKEY:
{
- switch (pt)
+ if (!(*last = p = pgp_parse_keyinfo (buff, l)))
{
- case PT_SECKEY: dprint (5, (debugfile, "PT_SECKEY: ")); break;
- case PT_PUBKEY: dprint (5, (debugfile, "PT_PUBKEY: ")); break;
- case PT_SUBKEY: dprint (5, (debugfile, "PT_SUBKEY: ")); break;
- case PT_SUBSECKEY: dprint (5, (debugfile, "PT_SUBSECKEY: ")); break;
+ err = 1;
+ break;
}
- if(p)
- end = &(p->next);
-
- if(!(*end = p = pgp_parse_keyinfo(buff, l)))
- break;
-
- dprint (5, (debugfile, " key-id: %s ", p->keyid));
-
+ last = &p->next;
addr = &p->address;
-
- if(pt == PT_SUBKEY || pt == PT_SUBSECKEY)
+
+ if (pt == PT_SUBKEY || pt == PT_SUBSECKEY)
{
p->flags |= KEYFLAG_SUBKEY;
- p->mainkey = supkey;
+ if (p != root)
+ p->parent = root;
}
- else
- supkey = p;
-
break;
}
-
+
case PT_SIG:
{
dprint (5, (debugfile, "PT_SIG\n"));
- pgp_parse_sig(buff, l, p);
+ pgp_parse_sig (buff, l, p);
break;
}
+
case PT_TRUST:
{
dprint (5, (debugfile, "PT_TRUST: "));
- if(last_pt == PT_SECKEY || last_pt == PT_PUBKEY ||
- last_pt == PT_SUBKEY || last_pt == PT_SUBSECKEY)
+ if (p && (last_pt == PT_SECKEY || last_pt == PT_PUBKEY ||
+ last_pt == PT_SUBKEY || last_pt == PT_SUBSECKEY))
{
- if(buff[1] & 0x20)
+ if (buff[1] & 0x20)
{
dprint (5, (debugfile, " disabling %s\n", p->keyid));
p->flags |= KEYFLAG_DISABLED;
}
}
- else if(last_pt == PT_NAME)
+ else if (last_pt == PT_NAME && uid)
{
uid->trust = buff[1];
- dprint (5, (debugfile, " setting trust for \"%s\" to %d.\n",
- uid->addr, uid->trust));
+ dprint (5, (debugfile, " setting trust for \"%s\" to %d.\n",
+ uid->addr, uid->trust));
}
break;
}
@@ -818,94 +932,142 @@ static KEYINFO *pgp_read_keyring(const char *fname)
char *chr;
dprint (5, (debugfile, "PT_NAME: "));
-
- if(!addr) break;
-
- chr = safe_malloc(l);
- memcpy(chr, buff + 1, l - 1);
- chr[l-1] = '\0';
-
+
+ if (!addr)
+ break;
+
+ chr = safe_malloc (l);
+ memcpy (chr, buff + 1, l - 1);
+ chr[l - 1] = '\0';
+
dprint (5, (debugfile, "\"%s\"\n", chr));
-
- mutt_decode_utf8_string(chr, chs);
- *addr = mutt_new_list();
- (*addr)->data = safe_malloc(sizeof(PGPUID));
- uid = (PGPUID *) (*addr)->data;
+
+ mutt_decode_utf8_string (chr, chs);
+ *addr = uid = safe_calloc (sizeof (pgp_uid_t), 1); /* XXX */
uid->addr = chr;
+ uid->parent = p;
uid->trust = 0;
- addr = &(*addr)->next;
-
+ addr = &uid->next;
+
/* the following tags are generated by
* pgp 2.6.3in.
*/
-
- if(strstr(chr, "ENCR"))
+
+ if (strstr (chr, "ENCR"))
p->flags |= KEYFLAG_PREFER_ENCRYPTION;
- if(strstr(chr, "SIGN"))
+ if (strstr (chr, "SIGN"))
p->flags |= KEYFLAG_PREFER_SIGNING;
-
+
break;
}
}
- }
- fclose(fp);
-
-#ifdef DEBUG
- if (debuglevel >= 4)
- {
- KEYINFO *dbp;
- LIST *lp;
- fprintf (debugfile, "\n\npgp_read_keyring: START KEYRING DUMP.\n");
-
- for (dbp = db; dbp; dbp = dbp->next)
- {
- fprintf (debugfile, "%s [len=%d, flags=%d]\n", dbp->keyid, dbp->keylen, dbp->flags);
- for (lp = dbp->address; lp; lp=lp->next)
- {
- fprintf (debugfile, " %s [%d]\n", ((PGPUID *)lp->data)->addr,
- ((PGPUID *)lp->data)->trust);
- }
- }
-
- fprintf (debugfile, "\nEND KEYRING DUMP.\n\n");
+ fgetpos (fp, &pos);
}
-#endif
+
+ if (err)
+ pgp_free_key (&root);
- return db;
+ return root;
}
-KEYINFO *pgp_read_pubring(struct pgp_vinfo *pgp)
+int pgp_string_matches_hint (const char *s, LIST * hints)
{
- return pgp_read_keyring(NONULL(*pgp->pubring));
-}
+ if (!hints)
+ return 1;
-KEYINFO *pgp_read_secring(struct pgp_vinfo *pgp)