summaryrefslogtreecommitdiffstats
path: root/gnupgparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnupgparse.c')
-rw-r--r--gnupgparse.c340
1 files changed, 192 insertions, 148 deletions
diff --git a/gnupgparse.c b/gnupgparse.c
index 306b6c87..f62bb659 100644
--- a/gnupgparse.c
+++ b/gnupgparse.c
@@ -1,19 +1,23 @@
/*
* Copyright (C) 1998 Werner Koch <werner.koch@guug.de>
+ * Copyright (C) 1999 Thomas Roessler <roessler@guug.de>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later
+ * version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more
+ * details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ * 02139, USA.
*/
@@ -48,169 +52,209 @@
* - signature class
*/
-static KEYINFO *parse_pub_line( char *buf, int *is_subkey )
+static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k)
{
- KEYINFO *k=NULL;
- PGPUID *uid = NULL;
- int field = 0;
- char *pend, *p;
- int trust = 0;
-
- *is_subkey = 0;
- if( !*buf )
- return NULL;
- for( p = buf; p; p = pend ) {
- if( (pend = strchr(p, ':')) )
- *pend++ = 0;
- field++;
- if( field > 1 && !*p )
- continue;
-
- switch( field ) {
- case 1: /* record type */
- if( !mutt_strcmp(p,"pub") )
- ;
- else if( !mutt_strcmp(p,"sub") )
- *is_subkey = 1;
- else if( !mutt_strcmp(p,"sec") )
- ;
- else if( !mutt_strcmp(p,"ssb") )
- *is_subkey = 1;
- else
- return NULL;
- k = safe_malloc( sizeof(KEYINFO) );
- memset(k, 0, sizeof(KEYINFO) );
- break;
- case 2: /* trust info */
- switch( *p ) { /* look only at the first letter */
- case 'e': k->flags |= KEYFLAG_EXPIRED; break;
- case 'n': trust = 1; break;
- case 'm': trust = 2; break;
- case 'f': trust = 3; break;
- case 'u': trust = 3; break;
- case 'r': k->flags |= KEYFLAG_REVOKED; break;
- }
- break;
- case 3: /* key length */
- k->keylen = atoi(p); /* fixme: add validation checks */
- break;
- case 4: /* pubkey algo */
- k->algorithm = pgp_pkalgbytype(atoi(p));
- k->flags |= pgp_get_abilities(atoi(p));
- break;
- case 5: /* 16 hex digits with the long keyid. */
- /* We really should do a check here */
- k->keyid = safe_strdup(p);
- break;
- case 6: /* timestamp (1998-02-28) */
- break;
- case 7: /* valid for n days */
+ pgp_uid_t *uid = NULL;
+ int field = 0, is_uid = 0;
+ char *pend, *p;
+ int trust = 0;
+
+ *is_subkey = 0;
+ if (!*buf)
+ return NULL;
+ for (p = buf; p; p = pend)
+ {
+ if ((pend = strchr (p, ':')))
+ *pend++ = 0;
+ field++;
+ if (field > 1 && !*p)
+ continue;
+
+ switch (field)
+ {
+ case 1: /* record type */
+ {
+ if (!mutt_strcmp (p, "pub"))
+ ;
+ else if (!mutt_strcmp (p, "sub"))
+ *is_subkey = 1;
+ else if (!mutt_strcmp (p, "sec"))
+ ;
+ else if (!mutt_strcmp (p, "ssb"))
+ *is_subkey = 1;
+ else if (!mutt_strcmp (p, "uid"))
+ is_uid = 1;
+ else
+ return NULL;
+
+ if (!is_uid)
+ k = safe_calloc (sizeof (pgp_key_t), 1);
+
+ break;
+ }
+ case 2: /* trust info */
+ /*
+ * XXX - is this the owner-trust field?
+ *
+ * Actually, we'd need the trust gpg has into the
+ * association between a user ID and a key.
+ *
+ * - tlr
+ */
+ {
+ switch (*p)
+ { /* look only at the first letter */
+ case 'e':
+ k->flags |= KEYFLAG_EXPIRED;
break;
- case 8: /* Local id */
+ case 'n':
+ trust = 1;
break;
- case 9: /* ownertrust */
+ case 'm':
+ trust = 2;
break;
- case 10: /* name */
- if( !pend || !*p )
- break; /* empty field or no trailing colon */
- k->address = mutt_new_list();
- k->address->data = safe_malloc( sizeof(PGPUID) );
- uid = (PGPUID *)k->address->data;
- uid->addr = safe_strdup(p);
- uid->trust = trust;
+ case 'f':
+ trust = 3;
break;
- case 11: /* signature class */
+ case 'u':
+ trust = 3;
break;
- default:
+ case 'r':
+ k->flags |= KEYFLAG_REVOKED;
break;
}
+ break;
+ }
+ case 3: /* key length */
+ {
+ k->keylen = atoi (p); /* fixme: add validation checks */
+ break;
+ }
+ case 4: /* pubkey algo */
+ {
+ k->algorithm = pgp_pkalgbytype (atoi (p));
+ k->flags |= pgp_get_abilities (atoi (p));
+ break;
+ }
+ case 5: /* 16 hex digits with the long keyid. */
+ {
+ /* We really should do a check here */
+ k->keyid = safe_strdup (p);
+ break;
+
+ }
+ case 6: /* timestamp (1998-02-28) */
+ break;
+ case 7: /* valid for n days */
+ break;
+ case 8: /* Local id */
+ break;
+ case 9: /* ownertrust */
+ break;
+ case 10: /* name */
+ {
+ if (!pend || !*p)
+ break; /* empty field or no trailing colon */
+ uid = safe_calloc (sizeof (pgp_uid_t), 1);
+ uid->addr = safe_strdup (p);
+ uid->trust = trust;
+ uid->parent = k;
+ uid->next = k->address;
+ k->address = uid;
+
+ if (strstr (p, "ENCR"))
+ k->flags |= KEYFLAG_PREFER_ENCRYPTION;
+ if (strstr (p, "SIGN"))
+ k->flags |= KEYFLAG_PREFER_SIGNING;
+
+ break;
+ }
+ case 11: /* signature class */
+ break;
+ default:
+ break;
}
- return k;
+ }
+ return k;
}
-static pid_t gpg_invoke_list_keys(struct pgp_vinfo *pgp,
- FILE **pgpin, FILE **pgpout, FILE **pgperr,
- int pgpinfd, int pgpoutfd, int pgperrfd,
- const char *uids, int secret)
+static pid_t gpg_invoke_list_keys (struct pgp_vinfo *pgp,
+ FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
+ int pgpinfd, int pgpoutfd, int pgperrfd,
+ pgp_ring_t keyring,
+ LIST * hints)
{
char cmd[HUGE_STRING];
char tmpcmd[HUGE_STRING];
- char *cp;
- char *keylist;
-
+
/* we use gpgm here */
- snprintf(cmd, sizeof(cmd),
- "%sm --no-verbose --batch --with-colons --list-%skeys ",
- NONULL(*pgp->binary), secret? "secret-":"");
+ snprintf (cmd, sizeof (cmd),
+ "%sm --no-verbose --batch --with-colons --list-%skeys ",
+ NONULL (*pgp->binary), keyring == PGP_SECRING ? "secret-" : "");
- keylist = safe_strdup(uids);
- for(cp = strtok(keylist, " "); cp ; cp = strtok(NULL, " "))
+ for (; hints; hints = hints->next)
{
- snprintf(tmpcmd, sizeof(tmpcmd), "%s %s",
- cmd, cp);
- strcpy(cmd, tmpcmd);
+ snprintf (tmpcmd, sizeof (tmpcmd), "%s %s", cmd, (char *) hints->data);
+ strcpy (cmd, tmpcmd);
}
- safe_free((void **) &keylist);
- return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
- pgpinfd, pgpoutfd, pgperrfd);
+
+ return mutt_create_filter_fd (cmd, pgpin, pgpout, pgperr,
+ pgpinfd, pgpoutfd, pgperrfd);
}
-static KEYINFO *read_ring(struct pgp_vinfo *pgp, int secret )
+pgp_key_t *gpg_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring,
+ LIST * hints)
{
- FILE *fp;
- pid_t thepid;
- char buf[LONG_STRING];
- KEYINFO *db = NULL, **kend, *k = NULL, *kk, *mainkey=NULL;
- int is_sub;
- int devnull;
-
- if((devnull = open("/dev/null", O_RDWR)) == -1)
- return NULL;
-
- thepid = gpg_invoke_list_keys(pgp, NULL, &fp, NULL, -1, -1, devnull,
- NULL, secret);
- if( thepid == -1 )
- {
- close(devnull);
- return NULL;
- }
+ FILE *fp;
+ pid_t thepid;
+ char buf[LONG_STRING];
+ pgp_key_t *db = NULL, **kend, *k = NULL, *kk, *mainkey = NULL;
+ int is_sub;
+ int devnull;
- kend = &db;
- k = NULL;
- while( fgets( buf, sizeof(buf)-1, fp ) ) {
- kk = parse_pub_line(buf, &is_sub );
- if( !kk )
- continue;
- if( k )
- kend = &k->next;
- *kend = k = kk;
-
- if( is_sub ) {
- k->flags |= KEYFLAG_SUBKEY;
- k->mainkey = mainkey;
- }
- else
- mainkey = k;
- }
- if( ferror(fp) )
- mutt_perror("fgets");
+ if ((devnull = open ("/dev/null", O_RDWR)) == -1)
+ return NULL;
- fclose( fp );
- mutt_wait_filter( thepid );
+ thepid = gpg_invoke_list_keys (pgp, NULL, &fp, NULL, -1, -1, devnull,
+ keyring, hints);
+ if (thepid == -1)
+ {
+ close (devnull);
+ return NULL;
+ }
- close(devnull);
-
- return db;
-}
+ kend = &db;
+ k = NULL;
+ while (fgets (buf, sizeof (buf) - 1, fp))
+ {
+ kk = parse_pub_line (buf, &is_sub, k);
+ if (!kk)
+ continue;
+ /* Only append kk to the list if it's new. */
+ if (kk != k)
+ {
+ if (k)
+ kend = &k->next;
+ *kend = k = kk;
+
+ if (is_sub)
+ {
+ k->flags |= KEYFLAG_SUBKEY;
+ k->parent = mainkey;
+ }
+ else
+ mainkey = k;
+ }
+ }
+ if (ferror (fp))
+ mutt_perror ("fgets");
-KEYINFO *gpg_read_pubring(struct pgp_vinfo *pgp)
-{
- return read_ring( pgp, 0 );
-}
+ fclose (fp);
+ mutt_wait_filter (thepid);
+ close (devnull);
-KEYINFO *gpg_read_secring(struct pgp_vinfo *pgp)
-{
- return read_ring( pgp, 1 );
+ return db;
}
+