From: Thomas Roessler Date: Thu, 3 Jun 1999 07:27:43 +0000 (+0000) Subject: Experimental: New PGP invocation interface. The invocations are done X-Git-Tag: mutt-0-96-3-rel~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dddad7c776881afcb79b627c5e423b4dd1ac8959;p=mutt Experimental: New PGP invocation interface. The invocations are done through formats, so all this should fit more cleanly into mutt now. --- diff --git a/Makefile.am b/Makefile.am index e23670d7..a965e339 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,9 +4,9 @@ ## Use aclocal -I m4; automake --foreign AUTOMAKE_OPTIONS = foreign -EXTRA_PROGRAMS = mutt_dotlock +EXTRA_PROGRAMS = mutt_dotlock pgpring -bin_PROGRAMS = mutt @DOTLOCK_TARGET@ +bin_PROGRAMS = mutt @DOTLOCK_TARGET@ @PGPAUX_TARGET@ mutt_SOURCES = addrbook.c alias.c attach.c browser.c buffy.c color.c \ commands.c complete.c compose.c copy.c curs_lib.c curs_main.c date.c \ edit.c enter.c flags.c init.c filter.c from.c getdomain.c \ @@ -23,12 +23,12 @@ DEFS=-DSHAREDIR=\"$(sharedir)\" -DSYSCONFDIR=\"$(sysconfdir)\" \ -DBINDIR=\"$(bindir)\" -DHAVE_CONFIG_H=1 INCLUDES=-I. -I$(includedir) -non_us_sources = pgp.c pgpinvoke.c pgpkey.c pgppubring.c sha1dgst.c \ +non_us_sources = pgp.c pgpinvoke.c pgpkey.c pgplib.c sha1dgst.c \ gnupgparse.c sha.h sha_locl.h \ doc/language.txt doc/language50.txt OPS.PGP doc/PGP-Notes \ - OPS.MIX remailer.c remailer.h + OPS.MIX remailer.c remailer.h pgpewrap -EXTRA_mutt_SOURCES = pgp.c pgpinvoke.c pgpkey.c pgppubring.c sha1dgst.c \ +EXTRA_mutt_SOURCES = pgp.c pgpinvoke.c pgpkey.c pgplib.c sha1dgst.c \ gnupgparse.c resize.c dotlock.c pop.c imap.c socket.c remailer.c remailer.h browser.h @@ -40,7 +40,7 @@ EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP TODO configure acconfig.h attach.h \ reldate.h rfc1524.h rfc2047.h rfc822.h sha.h sha_locl.h \ sort.h mime.types VERSION prepare _regex.h OPS.MIX \ README.SECURITY remailer.c remailer.h browser.h Muttrc.in \ - lib.h extlib.c + lib.h extlib.c pgpewrap BUILT_SOURCES = mutt_dotlock.c keymap_defs.h @@ -48,6 +48,10 @@ mutt_dotlock_SOURCES = mutt_dotlock.c mutt_dotlock_LDADD = @LIBOBJS@ mutt_dotlock_DEPENDENCIES = @LIBOBJS@ +pgpring_SOURCES = pgppubring.c pgplib.c lib.c extlib.c sha1dgst.c +pgpring_LDADD = @LIBOBJS@ +pgpring_DEPENDENCIES = @LIBOBJS@ + mutt_dotlock.c: dotlock.c cp $(srcdir)/dotlock.c mutt_dotlock.c diff --git a/compose.c b/compose.c index dd7a2b9e..221f3493 100644 --- a/compose.c +++ b/compose.c @@ -132,8 +132,6 @@ static int pgp_send_menu (int bits, int *redraw) char input_signas[SHORT_STRING]; char input_micalg[SHORT_STRING]; - struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_SIGN); - switch (mutt_multi_choice (_("(e)ncrypt, (s)ign, sign (a)s, (b)oth, select (m)ic algorithm, or (f)orget it? "), _("esabmf"))) { @@ -149,7 +147,7 @@ static int pgp_send_menu (int bits, int *redraw) unset_option(OPTPGPCHECKTRUST); - if (pgp && (p = pgp_ask_for_key (pgp, _("Sign as: "), NULL, KEYFLAG_CANSIGN, PGP_PUBRING))) + if ((p = pgp_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN, PGP_PUBRING))) { snprintf (input_signas, sizeof (input_signas), "0x%s", pgp_keyid (p)); safe_free((void **) &PgpSignAs); PgpSignAs = safe_strdup (input_signas); diff --git a/configure.in b/configure.in index 300ef9ef..a4a14faa 100644 --- a/configure.in +++ b/configure.in @@ -72,10 +72,11 @@ else fi if test $PGP != no || test $PGPK != no || test $GPG != no ; then - MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS pgp.o pgpinvoke.o pgpkey.o pgppubring.o sha1dgst.o gnupgparse.o" + PGPAUX_TARGET="pgpring pgpewrap" + MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS pgp.o pgpinvoke.o pgpkey.o pgplib.o gnupgparse.o" OPS="$OPS \$(srcdir)/OPS.PGP" fi - + AC_ARG_WITH(mixmaster, [ --with-mixmaster[=PATH] include Mixmaster support], [if test -x "$withval" ; then MIXMASTER="$withval" @@ -90,6 +91,8 @@ else fi AC_SUBST(OPS) +AC_SUBST(PGPAUX_TARGET) + AC_DEFINE_UNQUOTED(SUBVERSION, "$SUBVERSION") AC_SUBST(SUBVERSION) diff --git a/contrib/gpg.rc b/contrib/gpg.rc new file mode 100644 index 00000000..41799cf9 --- /dev/null +++ b/contrib/gpg.rc @@ -0,0 +1,40 @@ +# -*-muttrc-*- +# +# Command formats for gpg. +# +# $Id$ +# + +# decode application/pgp +set pgp_decode_command="gpg %?p?--passphrase-fd 0? --no-verbose --batch -o - --decrypt %f" + +# verify a pgp/mime signature +set pgp_verify_command="gpg --no-verbose --batch -o - --verify %s %f" + +# decrypt a pgp/mime attachment +set pgp_decrypt_command="gpg --passphrase-fd 0 --no-verbose --batch -o - --decrypt %f" + +# create a pgp/mime signed attachment +set pgp_sign_command="gpg --no-verbose --batch -o - --passphrase-fd 0 --detach-sign --textmode --armor %?a?-u %a? %f" + +# create a pgp/mime encrypted attachment +set pgp_encrypt_only_command="pgpewrap gpg --no-verbose -v --batch -o - --encrypt --textmode --armor --always-trust -- -r %r + +# create a pgp/mime encrypted and signed attachment +set pgp_encrypt_sign_command="pgpewrap gpg --passphrase-fd 0 --no-verbose -v --batch -o - --encrypt --sign %?a?-u %a? --textmode --armor --always-trust -- -r %r + +# import a key into the public key ring +set pgp_import_command="gpgm --no-verbose --import -v %f" + +# export a key from the public key ring +set pgp_export_command="gpgm --no-verbose --export --armor %r" + +# verify a key +set pgp_verify_key_command="gpgm --no-verbose --batch --fingerprint --check-sigs + +# read in the public key ring +set pgp_list_pubring_command="gpgm --no-verbose --batch --with-colons --list-keys %r" + +# read in the secret key ring +set pgp_list_secring_command="gpgm --no-verbose --batch --with-colons --list-secret-keys %r" + diff --git a/contrib/pgp2.rc b/contrib/pgp2.rc new file mode 100644 index 00000000..f1a6bd6b --- /dev/null +++ b/contrib/pgp2.rc @@ -0,0 +1,41 @@ +# -*-muttrc-*- +# +# PGP command formats for PGP 2. +# +# $Id$ +# + +# decode application/pgp +set pgp_decode_command="%?p?PGPPASSFD=0; export PGPPASSFD;? cat %?p?-? %f | pgp +language=mutt +verbose=0 +batchmode -f" + +# verify a pgp/mime signature +set pgp_verify_command="pgp +language=mutt +verbose=0 +batchmode %f %s" + +# decrypt a pgp/mime attachment +set pgp_decrypt_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgp +language=mutt +verbose=0 +batchmode -f" + +# create a pgp/mime signed attachment +set pgp_sign_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgp +language=mutt +verbose=0 +batchmode -abfst %?a? -u %a?" + +# create a pgp/mime encrypted attachment +set pgp_encrypt_only_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgp +language=mutt +verbose=0 +batchmode +aeft %r" + +# create a pgp/mime encrypted and signed attachment +set pgp_encrypt_sign_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgp +language=mutt +verbose=0 +batchmode +aefts %?a?-u %a? %r" + +# import a key into the public key ring +set pgp_import_command="pgp -ka %f +language=mutt" + +# export a key from the public key ring +set pgp_export_command="pgp -kxaf +language=mutt %r" + +# verify a key +set pgp_verify_key_command="pgp -kcc +language=mutt %r" + +# read in the public key ring +set pgp_list_pubring_command="pgpring -k $PGPPATH/pubring.pgp %r" + +# read in the secret key ring +set pgp_list_secring_command="pgpring -k $PGPPATH/secring.pgp %r" + + diff --git a/contrib/pgp5.rc b/contrib/pgp5.rc new file mode 100644 index 00000000..0a54f941 --- /dev/null +++ b/contrib/pgp5.rc @@ -0,0 +1,41 @@ +# -*-muttrc-*- +# +# PGP command formats for PGP 5. +# +# $Id$ +# + +# decode application/pgp +set pgp_decode_command="%?p?PGPPASSFD=0; export PGPPASSFD;? cat %?p?-? %f | pgpv +language=mutt +verbose=0 +batchmode -f --OutputInformationFD=0" + +# verify a pgp/mime signature +set pgp_verify_command="pgpv +language=mutt +verbose=0 +batchmode --OutputInformationFD=1 %f %s" + +# decrypt a pgp/mime attachment +set pgp_decrypt_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgpv +language=mutt +verbose=0 +batchmode --OutputInformationFD=2 -f" + +# create a pgp/mime signed attachment +set pgp_sign_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgps +language=mutt +verbose=0 +batchmode -abft %?a? -u %a?" + +# create a pgp/mime encrypted attachment +set pgp_encrypt_only_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgpewrap pgpe +language=mutt +verbose=0 +batchmode +nobatchinvalidkeys=off -aft -- -r %r" + +# create a pgp/mime encrypted and signed attachment +set pgp_encrypt_sign_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgpewrap pgpe +language=mutt +verbose=0 +batchmode +nobatchinvalidkeys=off -afts %?a? -u %a? -- -r %r" + +# import a key into the public key ring +set pgp_import_command="pgpk -a +language=mutt --OutputInformationFD=1 %f" + +# export a key from the public key ring +set pgp_export_command="pgpk -xa +language=mutt --OutputInformationFD=1 %r" + +# verify a key +set pgp_verify_key_command="pgpk -c +batchmode +language=mutt --OutputInformationFD=1 %r" + +# read in the public key ring +set pgp_list_pubring_command="pgpring -k $PGPPATH/pubring.pkr %r" + +# read in the secret key ring +set pgp_list_secring_command="pgpring -k $PGPPATH/secring.skr %r" + + diff --git a/gnupgparse.c b/gnupgparse.c index 8e44fd60..b018035a 100644 --- a/gnupgparse.c +++ b/gnupgparse.c @@ -20,6 +20,15 @@ * 02139, USA. */ +/* + * NOTE + * + * This code used to be the parser for GnuPG's output. + * + * Nowadays, we are using an external pubring lister with PGP which mimics + * gpg's output format. + * + */ #include #include @@ -30,10 +39,14 @@ #include #include #include +#include #include "mutt.h" #include "pgp.h" +#include "charset.h" +/* for hexval */ +#include "mime.h" /**************** * Read the GNUPG keys. For now we read the complete keyring by @@ -52,6 +65,29 @@ * - signature class */ +/* decode the backslash-escaped user ids. */ + +static CHARSET *_chs; + +static void fix_uid (char *uid) +{ + char *s, *d; + + for (s = d = uid; *s;) + { + if (*s == '\\' && *(s+1) == 'x' && isxdigit (*(s+2)) && isxdigit (*(s+3))) + { + *d++ = hexval (*(s+2)) << 4 | hexval (*(s+3)); + s += 4; + } + else + *d++ = *s++; + } + *d = '\0'; + + mutt_decode_utf8_string (d, _chs); +} + static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k) { pgp_uid_t *uid = NULL; @@ -62,6 +98,9 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k) *is_subkey = 0; if (!*buf) return NULL; + + dprint (2, (debugfile, "parse_pub_line: buf = `%s'\n", buf)); + for (p = buf; p; p = pend) { if ((pend = strchr (p, ':'))) @@ -74,6 +113,8 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k) { case 1: /* record type */ { + dprint (2, (debugfile, "record type: %s\n", p)); + if (!mutt_strcmp (p, "pub")) ; else if (!mutt_strcmp (p, "sub")) @@ -94,6 +135,9 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k) } case 2: /* trust info */ { + + dprint (2, (debugfile, "trust info: %s\n", p)); + switch (*p) { /* look only at the first letter */ case 'e': @@ -102,10 +146,6 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k) case 'r': k->flags |= KEYFLAG_REVOKED; break; - - /* produce "undefined trust" as long as gnupg doesn't - * have a proper trust model. - */ case 'n': trust = 1; break; @@ -123,17 +163,26 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k) } case 3: /* key length */ { + + dprint (2, (debugfile, "key len: %s\n", p)); + k->keylen = atoi (p); /* fixme: add validation checks */ break; } case 4: /* pubkey algo */ { + + dprint (2, (debugfile, "pubkey algorithm: %s\n", p)); + + k->numalg = atoi (p); k->algorithm = pgp_pkalgbytype (atoi (p)); k->flags |= pgp_get_abilities (atoi (p)); break; } case 5: /* 16 hex digits with the long keyid. */ { + dprint (2, (debugfile, "key id: %s\n", p)); + /* We really should do a check here */ k->keyid = safe_strdup (p); break; @@ -143,6 +192,9 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k) { char tstr[11]; struct tm time; + + dprint (2, (debugfile, "time stamp: %s\n", p)); + if (!p) break; time.tm_sec = 0; @@ -167,7 +219,11 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k) { if (!pend || !*p) break; /* empty field or no trailing colon */ + + dprint (2, (debugfile, "user ID: %s\n", p)); + uid = safe_calloc (sizeof (pgp_uid_t), 1); + fix_uid (p); uid->addr = safe_strdup (p); uid->trust = trust; uid->parent = k; @@ -190,32 +246,7 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *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, - pgp_ring_t keyring, - LIST * hints) -{ - char cmd[HUGE_STRING]; - char tmpcmd[HUGE_STRING]; - - /* we use gpgm here */ - snprintf (cmd, sizeof (cmd), - "%sm --no-verbose --batch --with-colons --list-%skeys ", - NONULL (*pgp->binary), keyring == PGP_SECRING ? "secret-" : ""); - - for (; hints; hints = hints->next) - { - snprintf (tmpcmd, sizeof (tmpcmd), "%s %s", cmd, (char *) hints->data); - strcpy (cmd, tmpcmd); - } - - return mutt_create_filter_fd (cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} - -pgp_key_t *gpg_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring, - LIST * hints) +pgp_key_t *pgp_get_candidates (pgp_ring_t keyring, LIST * hints) { FILE *fp; pid_t thepid; @@ -227,7 +258,9 @@ pgp_key_t *gpg_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring, if ((devnull = open ("/dev/null", O_RDWR)) == -1) return NULL; - thepid = gpg_invoke_list_keys (pgp, NULL, &fp, NULL, -1, -1, devnull, + _chs = mutt_get_charset (Charset); + + thepid = pgp_invoke_list_keys (NULL, &fp, NULL, -1, -1, devnull, keyring, hints); if (thepid == -1) { diff --git a/init.c b/init.c index 22436654..3195581c 100644 --- a/init.c +++ b/init.c @@ -1622,53 +1622,6 @@ void mutt_init (int skip_sys_rc, LIST *commands) Tempdir = safe_strdup ((p = getenv ("TMPDIR")) ? p : "/tmp"); - - -#ifdef _PGPPATH -#ifdef _PGPV2PATH - PgpV2 = safe_strdup (_PGPV2PATH); - if ((p = getenv("PGPPATH")) != NULL) - { - snprintf (buffer, sizeof (buffer), "%s/pubring.pgp", p); - PgpV2Pubring = safe_strdup (buffer); - snprintf (buffer, sizeof (buffer), "%s/secring.pgp", p); - PgpV2Secring = safe_strdup (buffer); - } - else - { - snprintf (buffer, sizeof (buffer), "%s/.pgp/pubring.pgp", NONULL(Homedir)); - PgpV2Pubring = safe_strdup (buffer); - snprintf (buffer, sizeof (buffer), "%s/.pgp/secring.pgp", NONULL(Homedir)); - PgpV2Secring = safe_strdup (buffer); - } -#endif - -#ifdef _PGPV3PATH - PgpV3 = safe_strdup (_PGPV3PATH); - if ((p = getenv("PGPPATH")) != NULL) - { - snprintf (buffer, sizeof (buffer), "%s/pubring.pkr", p); - PgpV3Pubring = safe_strdup (buffer); - snprintf (buffer, sizeof (buffer), "%s/secring.skr", p); - PgpV3Secring = safe_strdup (buffer); - } - else - { - snprintf (buffer, sizeof (buffer), "%s/.pgp/pubring.pkr", NONULL(Homedir)); - PgpV3Pubring = safe_strdup (buffer); - snprintf (buffer, sizeof (buffer), "%s/.pgp/secring.skr", NONULL(Homedir)); - PgpV3Secring = safe_strdup (buffer); - } -#endif - -#ifdef _PGPGPGPATH - PgpGpg = safe_strdup (_PGPGPGPATH); -#endif - -#endif /* _PGPPATH */ - - - #ifdef USE_POP PopUser = safe_strdup (Username); #endif diff --git a/init.h b/init.h index 47afd71f..c381bcbe 100644 --- a/init.h +++ b/init.h @@ -186,7 +186,11 @@ struct option_t MuttVars[] = { { "pgp_autosign", DT_BOOL, R_NONE, OPTPGPAUTOSIGN, 0 }, { "pgp_autoencrypt", DT_BOOL, R_NONE, OPTPGPAUTOENCRYPT, 0 }, + +# if 0 { "pgp_encryptself", DT_BOOL, R_NONE, OPTPGPENCRYPTSELF, 1 }, +# endif + { "pgp_entry_format", DT_STR, R_NONE, UL &PgpEntryFormat, UL "%4n %t%f %4l/0x%k %-4a %2c %u" }, { "pgp_long_ids", DT_BOOL, R_NONE, OPTPGPLONGIDS, 0 }, { "pgp_replyencrypt", DT_BOOL, R_NONE, OPTPGPREPLYENCRYPT, 0 }, @@ -199,35 +203,23 @@ struct option_t MuttVars[] = { { "pgp_strict_enc", DT_BOOL, R_NONE, OPTPGPSTRICTENC, 1 }, { "pgp_timeout", DT_NUM, R_NONE, UL &PgpTimeout, 300 }, { "pgp_verify_sig", DT_QUAD, R_NONE, OPT_VERIFYSIG, M_YES }, + { "pgp_sort_keys", DT_SORT|DT_SORT_KEYS, R_NONE, UL &PgpSortKeys, SORT_ADDRESS }, - { "pgp_v2", DT_PATH, R_NONE, UL &PgpV2, 0 }, - { "pgp_v2_language", DT_STR, R_NONE, UL &PgpV2Language, UL "en" }, - { "pgp_v2_pubring", DT_PATH, R_NONE, UL &PgpV2Pubring, 0 }, - { "pgp_v2_secring", DT_PATH, R_NONE, UL &PgpV2Secring, 0 }, - - { "pgp_v5", DT_PATH, R_NONE, UL &PgpV3, 0 }, - { "pgp_v5_language", DT_STR, R_NONE, UL &PgpV3Language, 0 }, - { "pgp_v5_pubring", DT_PATH, R_NONE, UL &PgpV3Pubring, 0 }, - { "pgp_v5_secring", DT_PATH, R_NONE, UL &PgpV3Secring, 0 }, - - { "pgp_gpg", DT_PATH, R_NONE, UL &PgpGpg, 0 }, + /* XXX Default values! */ -# ifdef HAVE_PGP2 - { "pgp_default_version", DT_STR, R_NONE, UL &PgpDefaultVersion, UL "pgp2" }, -# else -# ifdef HAVE_PGP5 - { "pgp_default_version", DT_STR, R_NONE, UL &PgpDefaultVersion, UL "pgp5" }, -# else -# ifdef HAVE_GPG - { "pgp_default_version", DT_STR, R_NONE, UL &PgpDefaultVersion, UL "gpg" }, -# endif -# endif -# endif - { "pgp_receive_version", DT_STR, R_NONE, UL &PgpReceiveVersion, UL "default" }, - { "pgp_send_version", DT_STR, R_NONE, UL &PgpSendVersion, UL "default" }, - { "pgp_sort_keys", DT_SORT|DT_SORT_KEYS, R_NONE, UL &PgpSortKeys, SORT_ADDRESS }, - { "pgp_key_version", DT_STR, R_NONE, UL &PgpKeyVersion, UL "default" }, + { "pgp_decode_command", DT_STR, R_NONE, UL &PgpDecodeCommand, 0}, + { "pgp_verify_command", DT_STR, R_NONE, UL &PgpVerifyCommand, 0}, + { "pgp_decrypt_command", DT_STR, R_NONE, UL &PgpDecryptCommand, 0}, + { "pgp_sign_command", DT_STR, R_NONE, UL &PgpSignCommand, 0}, + { "pgp_encrypt_sign_command", DT_STR, R_NONE, UL &PgpEncryptSignCommand, 0}, + { "pgp_encrypt_only_command", DT_STR, R_NONE, UL &PgpEncryptOnlyCommand, 0}, + { "pgp_import_command", DT_STR, R_NONE, UL &PgpImportCommand, 0}, + { "pgp_export_command", DT_STR, R_NONE, UL &PgpExportCommand, 0}, + { "pgp_verify_key_command", DT_STR, R_NONE, UL &PgpVerifyKeyCommand, 0}, + { "pgp_list_secring_command", DT_STR, R_NONE, UL &PgpListSecringCommand, 0}, + { "pgp_list_pubring_command", DT_STR, R_NONE, UL &PgpListPubringCommand, 0}, + { "forward_decrypt", DT_BOOL, R_NONE, OPTFORWDECRYPT, 1 }, { "forw_decrypt", DT_SYN, R_NONE, UL "forward_decrypt", 0 }, #endif /* _PGPPATH */ diff --git a/mutt.h b/mutt.h index 38448464..e19556f6 100644 --- a/mutt.h +++ b/mutt.h @@ -343,7 +343,9 @@ enum OPTPGPREPLYENCRYPT, OPTPGPREPLYSIGN, OPTPGPREPLYSIGNENCRYPTED, +#if 0 OPTPGPENCRYPTSELF, +#endif OPTPGPRETAINABLESIG, OPTPGPSTRICTENC, OPTFORWDECRYPT, diff --git a/pgp.c b/pgp.c index e590c3c5..df1b15fe 100644 --- a/pgp.c +++ b/pgp.c @@ -45,75 +45,6 @@ char PgpPass[STRING]; static time_t PgpExptime = 0; /* when does the cached passphrase expire? */ -static struct pgp_vinfo pgp_vinfo[] = -{ - - { PGP_V2, - "pgp2", - &PgpV2, &PgpV2Pubring, &PgpV2Secring, &PgpV2Language, - pgp_get_candidates, - pgp_v2_invoke_decode, pgp_v2_invoke_verify, pgp_v2_invoke_decrypt, - pgp_v2_invoke_sign, pgp_v2_invoke_encrypt, pgp_v2_invoke_import, - pgp_v2_invoke_export, pgp_v2_invoke_verify_key - }, - - { PGP_V3, - "pgp3", - &PgpV3, &PgpV3Pubring, &PgpV3Secring, &PgpV3Language, - pgp_get_candidates, - pgp_v3_invoke_decode, pgp_v3_invoke_verify, pgp_v3_invoke_decrypt, - pgp_v3_invoke_sign, pgp_v3_invoke_encrypt, pgp_v3_invoke_import, - pgp_v3_invoke_export, pgp_v3_invoke_verify_key - }, - - { PGP_V3, - "pgp5", - &PgpV3, &PgpV3Pubring, &PgpV3Secring, &PgpV3Language, - pgp_get_candidates, - pgp_v3_invoke_decode, pgp_v3_invoke_verify, pgp_v3_invoke_decrypt, - pgp_v3_invoke_sign, pgp_v3_invoke_encrypt, pgp_v3_invoke_import, - pgp_v3_invoke_export, pgp_v3_invoke_verify_key - }, - - { PGP_GPG, - "gpg", - &PgpGpg, &PgpGpgDummy, &PgpGpgDummy, &PgpGpgDummy, - gpg_get_candidates, - pgp_gpg_invoke_decode, pgp_gpg_invoke_verify, pgp_gpg_invoke_decrypt, - pgp_gpg_invoke_sign, pgp_gpg_invoke_encrypt, pgp_gpg_invoke_import, - pgp_gpg_invoke_export, pgp_gpg_invoke_verify_key - }, - - { PGP_UNKNOWN, - NULL, - NULL, NULL, NULL, NULL, - NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL - } -}; - -static struct -{ - enum pgp_ops op; - char **str; -} -pgp_opvers[] = -{ - { PGP_DECODE, &PgpReceiveVersion }, - { PGP_VERIFY, &PgpReceiveVersion }, - { PGP_DECRYPT, &PgpReceiveVersion }, - { PGP_SIGN, &PgpSendVersion }, - { PGP_ENCRYPT, &PgpSendVersion }, - { PGP_VERIFY_KEY, &PgpSendVersion }, - { PGP_IMPORT, &PgpKeyVersion }, - { PGP_EXPORT, &PgpKeyVersion }, - { PGP_LAST_OP, NULL } -}; - - - void pgp_void_passphrase (void) { memset (PgpPass, 0, sizeof (PgpPass)); @@ -147,37 +78,6 @@ void mutt_forget_passphrase (void) } -struct pgp_vinfo *pgp_get_vinfo(enum pgp_ops op) -{ - int i; - char *version = "default"; - char msg[LONG_STRING]; - - for(i = 0; pgp_opvers[i].op != PGP_LAST_OP; i++) - { - if(pgp_opvers[i].op == op) - { - version = *pgp_opvers[i].str; - break; - } - } - - if (!mutt_strcasecmp(version, "default")) - version = PgpDefaultVersion; - - for(i = 0; pgp_vinfo[i].name; i++) - { - if(!mutt_strcasecmp(pgp_vinfo[i].name, version)) - return &pgp_vinfo[i]; - } - - snprintf(msg, sizeof(msg), _("Unknown PGP version \"%s\"."), - version); - mutt_error(msg); - - return NULL; -} - char *pgp_keyid(pgp_key_t *k) { if((k->flags & KEYFLAG_SUBKEY) && k->parent) @@ -229,11 +129,7 @@ void pgp_application_pgp_handler (BODY *m, STATE *s) FILE *pgpout = NULL, *pgpin, *pgperr; FILE *tmpfp; pid_t thepid; - struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_DECODE); - if(!pgp) - return; - fseek (s->fpin, m->offset, 0); last_pos = m->offset; @@ -308,8 +204,7 @@ void pgp_application_pgp_handler (BODY *m, STATE *s) fclose(tmpfp); - if ((thepid = pgp->invoke_decode (pgp, - &pgpin, NULL, + if ((thepid = pgp_invoke_decode (&pgpin, NULL, &pgperr, -1, fileno (pgpout), -1, tmpfname, @@ -622,7 +517,7 @@ static int pgp_write_signed(BODY *a, STATE *s, const char *tempfile) return 0; } -static int pgp_verify_one (BODY *sigbdy, STATE *s, const char *tempfile, struct pgp_vinfo *pgp) +static int pgp_verify_one (BODY *sigbdy, STATE *s, const char *tempfile) { char sigfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX]; FILE *fp, *pgpout, *pgperr; @@ -650,8 +545,7 @@ static int pgp_verify_one (BODY *sigbdy, STATE *s, const char *tempfile, struct pgp_current_time (s); - if((thepid = pgp->invoke_verify (pgp, - NULL, &pgpout, NULL, + if((thepid = pgp_invoke_verify (NULL, &pgpout, NULL, -1, -1, fileno(pgperr), tempfile, sigfile)) != -1) { @@ -683,16 +577,10 @@ void pgp_signed_handler (BODY *a, STATE *s) int protocol_major = TYPEOTHER; char *protocol_minor = NULL; - struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_VERIFY); - BODY **signatures = NULL; int sigcnt = 0; int i; - - if (!pgp) - return; - protocol = mutt_get_parameter ("protocol", a->parameter); a = a->parts; @@ -744,7 +632,7 @@ void pgp_signed_handler (BODY *a, STATE *s) { if (signatures[i]->type == TYPEAPPLICATION && !mutt_strcasecmp(signatures[i]->subtype, "pgp-signature")) - pgp_verify_one (signatures[i], s, tempfile, pgp); + pgp_verify_one (signatures[i], s, tempfile); else state_printf (s, _("[-- Warning: We can't verify %s/%s signatures. --]\n\n"), TYPE(signatures[i]), signatures[i]->subtype); @@ -776,106 +664,95 @@ void pgp_extract_keys_from_messages (HEADER *h) int i; STATE s; char tempfname[_POSIX_PATH_MAX]; - struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_IMPORT); - - if(!pgp) - return; - - if(h) + + if (h) { - mutt_parse_mime_message(Context, h); - if(h->pgp & PGPENCRYPT && !pgp_valid_passphrase()) + mutt_parse_mime_message (Context, h); + if(h->pgp & PGPENCRYPT && !pgp_valid_passphrase ()) return; } - memset(&s, 0, sizeof(STATE)); + memset (&s, 0, sizeof (STATE)); - mutt_mktemp(tempfname); - if(!(s.fpout = safe_fopen(tempfname, "w"))) + mutt_mktemp (tempfname); + if (!(s.fpout = safe_fopen (tempfname, "w"))) { - mutt_perror(tempfname); + mutt_perror (tempfname); return; } - set_option(OPTDONTHANDLEPGPKEYS); + set_option (OPTDONTHANDLEPGPKEYS); - if(!h) + if (!h) { - for(i = 0; i < Context->vcount; i++) + for (i = 0; i < Context->vcount; i++) { - if(Context->hdrs[Context->v2r[i]]->tagged) + if (Context->hdrs[Context->v2r[i]]->tagged) { - mutt_parse_mime_message(Context, Context->hdrs[Context->v2r[i]]); - if(Context->hdrs[Context->v2r[i]]->pgp & PGPENCRYPT + mutt_parse_mime_message (Context, Context->hdrs[Context->v2r[i]]); + if (Context->hdrs[Context->v2r[i]]->pgp & PGPENCRYPT && !pgp_valid_passphrase()) { - fclose(s.fpout); + fclose (s.fpout); goto bailout; } - mutt_pipe_message_to_state(Context->hdrs[Context->v2r[i]], &s); + mutt_pipe_message_to_state (Context->hdrs[Context->v2r[i]], &s); } } } else { - mutt_parse_mime_message(Context, h); - if(h->pgp & PGPENCRYPT && !pgp_valid_passphrase()) + mutt_parse_mime_message (Context, h); + if (h->pgp & PGPENCRYPT && !pgp_valid_passphrase()) { - fclose(s.fpout); + fclose (s.fpout); goto bailout; } - mutt_pipe_message_to_state(h, &s); + mutt_pipe_message_to_state (h, &s); } - fclose(s.fpout); - endwin(); - pgp->invoke_import(pgp, tempfname); - mutt_any_key_to_continue(NULL); + fclose (s.fpout); + endwin (); + pgp_invoke_import (tempfname); + mutt_any_key_to_continue (NULL); bailout: - mutt_unlink(tempfname); - unset_option(OPTDONTHANDLEPGPKEYS); + mutt_unlink (tempfname); + unset_option (OPTDONTHANDLEPGPKEYS); } -static void pgp_extract_keys_from_attachment(struct pgp_vinfo *pgp, - FILE *fp, BODY *top) +static void pgp_extract_keys_from_attachment (FILE *fp, BODY *top) { STATE s; FILE *tempfp; char tempfname[_POSIX_PATH_MAX]; - mutt_mktemp(tempfname); - if(!(tempfp = safe_fopen(tempfname, "w"))) + mutt_mktemp (tempfname); + if (!(tempfp = safe_fopen (tempfname, "w"))) { - mutt_perror(tempfname); + mutt_perror (tempfname); return; } - memset(&s, 0, sizeof(STATE)); + memset (&s, 0, sizeof (STATE)); s.fpin = fp; s.fpout = tempfp; - mutt_body_handler(top, &s); - - fclose(tempfp); + mutt_body_handler (top, &s); - pgp->invoke_import(pgp, tempfname); - mutt_any_key_to_continue(NULL); + fclose (tempfp); - mutt_unlink(tempfname); + pgp_invoke_import (tempfname); + mutt_any_key_to_continue (NULL); + mutt_unlink (tempfname); } void pgp_extract_keys_from_attachment_list (FILE *fp, int tag, BODY *top) { - struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_IMPORT); - - if(!pgp) - return; - if(!fp) { mutt_error _("Internal error. Inform ."); @@ -888,7 +765,7 @@ void pgp_extract_keys_from_attachment_list (FILE *fp, int tag, BODY *top) for(; top; top = top->next) { if(!tag || top->tagged) - pgp_extract_keys_from_attachment (pgp, fp, top); + pgp_extract_keys_from_attachment (fp, top); if(!tag) break; @@ -907,10 +784,6 @@ BODY *pgp_decrypt_part (BODY *a, STATE *s, FILE *fpout) char pgperrfile[_POSIX_PATH_MAX]; char pgptmpfile[_POSIX_PATH_MAX]; pid_t thepid; - struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_DECRYPT); - - if(!pgp) - return NULL; mutt_mktemp (pgperrfile); if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL) @@ -936,7 +809,7 @@ BODY *pgp_decrypt_part (BODY *a, STATE *s, FILE *fpout) mutt_copy_bytes (s->fpin, pgptmp, a->length); fclose (pgptmp); - if ((thepid = pgp->invoke_decrypt (pgp, &pgpin, &pgpout, NULL, -1, -1, + if ((thepid = pgp_invoke_decrypt (&pgpin, &pgpout, NULL, -1, -1, fileno (pgperr), pgptmpfile)) == -1) { fclose (pgperr); @@ -1119,10 +992,6 @@ static BODY *pgp_sign_message (BODY *a) int err = 0; int empty = 1; pid_t thepid; - struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_SIGN); - - if(!pgp) - return NULL; convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */ @@ -1146,8 +1015,8 @@ static BODY *pgp_sign_message (BODY *a) mutt_write_mime_body (a, sfp); fclose(sfp); - if((thepid = pgp->invoke_sign(pgp, &pgpin, &pgpout, &pgperr, - -1, -1, -1, signedfile)) == -1) + if ((thepid = pgp_invoke_sign (&pgpin, &pgpout, &pgperr, + -1, -1, -1, signedfile)) == -1) { mutt_perror _("Can't open PGP subprocess!"); fclose(fp); @@ -1241,11 +1110,7 @@ char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) ADDRESS *p; int i; pgp_key_t *k_info, *key; - struct pgp_vinfo *pgp = pgp_get_vinfo (PGP_ENCRYPT); - - if (!pgp) - return NULL; - + for (i = 0; i < 3; i++) { switch (i) @@ -1272,14 +1137,14 @@ char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) { snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox); if (mutt_yesorno (buf, M_YES) == M_YES) - k_info = pgp_getkeybystr (pgp, keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING); + k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING); } - if (k_info == NULL && (k_info = pgp_getkeybyaddr (pgp, p, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) + if (k_info == NULL && (k_info = pgp_getkeybyaddr (p, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) { snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), p->mailbox); - if ((key = pgp_ask_for_key (pgp, buf, p->mailbox, + if ((key = pgp_ask_for_key (buf, p->mailbox, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) { safe_free ((void **)&keylist); @@ -1317,10 +1182,6 @@ static BODY *pgp_encrypt_message (BODY *a, char *keylist, int sign) int err = 0; int empty; pid_t thepid; - struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_ENCRYPT); - - if(!pgp) - return NULL; mutt_mktemp (tempfile); if ((fpout = safe_fopen (tempfile, "w+")) == NULL) @@ -1357,9 +1218,9 @@ static BODY *pgp_encrypt_message (BODY *a, char *keylist, int sign) mutt_write_mime_body (a, fptmp); fclose(fptmp); - if ((thepid = pgp->invoke_encrypt (pgp, &pgpin, NULL, NULL, -1, - fileno (fpout), fileno (pgperr), - pgpinfile, keylist, sign)) == -1) + if ((thepid = pgp_invoke_encrypt (&pgpin, NULL, NULL, -1, + fileno (fpout), fileno (pgperr), + pgpinfile, keylist, sign)) == -1) { fclose (pgperr); unlink(pgpinfile); diff --git a/pgp.h b/pgp.h index 8e5580e7..005e7403 100644 --- a/pgp.h +++ b/pgp.h @@ -19,155 +19,30 @@ #ifdef _PGPPATH -#define PGPENCRYPT 1 -#define PGPSIGN 2 -#define PGPKEY 4 +#include "pgplib.h" -#define KEYFLAG_CANSIGN (1 << 0) -#define KEYFLAG_CANENCRYPT (1 << 1) -#define KEYFLAG_EXPIRED (1 << 8) -#define KEYFLAG_REVOKED (1 << 9) -#define KEYFLAG_DISABLED (1 << 10) -#define KEYFLAG_SUBKEY (1 << 11) -#define KEYFLAG_CRITICAL (1 << 12) -#define KEYFLAG_PREFER_ENCRYPTION (1 << 13) -#define KEYFLAG_PREFER_SIGNING (1 << 14) - -#define KEYFLAG_CANTUSE (KEYFLAG_DISABLED|KEYFLAG_REVOKED|KEYFLAG_EXPIRED) -#define KEYFLAG_RESTRICTIONS (KEYFLAG_CANTUSE|KEYFLAG_CRITICAL) - -#define KEYFLAG_ABILITIES (KEYFLAG_CANSIGN|KEYFLAG_CANENCRYPT|KEYFLAG_PREFER_ENCRYPTION|KEYFLAG_PREFER_SIGNING) - -typedef struct pgp_keyinfo -{ - char *keyid; - struct pgp_uid *address; - int flags; - short keylen; - time_t gen_time; - const char *algorithm; - struct pgp_keyinfo *parent; - struct pgp_keyinfo *next; -} -pgp_key_t; - -typedef struct pgp_uid -{ - char *addr; - short trust; - struct pgp_keyinfo *parent; - struct pgp_uid *next; -} -pgp_uid_t; - -enum pgp_version -{ - PGP_V2, - PGP_V3, - PGP_GPG, - PGP_UNKNOWN -}; - -enum pgp_ring -{ - PGP_PUBRING, - PGP_SECRING -}; - -typedef enum pgp_ring pgp_ring_t; - -enum pgp_ops -{ - PGP_DECODE, /* application/pgp */ - PGP_VERIFY, /* PGP/MIME, signed */ - PGP_DECRYPT, /* PGP/MIME, encrypted */ - PGP_SIGN, /* sign data */ - PGP_ENCRYPT, /* encrypt data */ - PGP_IMPORT, /* extract keys from messages */ - PGP_VERIFY_KEY, /* verify key when selecting */ - PGP_EXPORT, /* extract keys from key ring */ - PGP_LAST_OP -}; - -struct pgp_vinfo -{ - - /* data */ - - enum pgp_version v; - char *name; - char **binary; - char **pubring; - char **secring; - char **language; - - /* functions */ - - pgp_key_t *(*get_candidates) (struct pgp_vinfo *, pgp_ring_t, LIST *); - - pid_t (*invoke_decode) (struct pgp_vinfo *, FILE **, FILE **, FILE **, - int, int, int, - const char *, int); - - pid_t (*invoke_verify) (struct pgp_vinfo *, FILE **, FILE **, FILE **, - int, int, int, - const char *, const char *); - - pid_t (*invoke_decrypt) (struct pgp_vinfo *, FILE **, FILE **, FILE **, - int, int, int, - const char *); - - pid_t (*invoke_sign) (struct pgp_vinfo *, FILE **, FILE **, FILE **, - int, int, int, - const char *); - - pid_t (*invoke_encrypt) (struct pgp_vinfo *, FILE **, FILE **, FILE **, - int, int, int, - const char *, const char *, int); - - void (*invoke_import) (struct pgp_vinfo *, const char *); - - pid_t (*invoke_export) (struct pgp_vinfo *, FILE **, FILE **, FILE **, - int, int, int, - const char *); - - pid_t (*invoke_verify_key) (struct pgp_vinfo *, FILE **, FILE **, FILE **, - int, int, int, - const char *); - -}; - - -WHERE char *PgpV2; -WHERE char *PgpV2Language; -WHERE char *PgpV2Pubring; -WHERE char *PgpV2Secring; - -WHERE char *PgpV3; -WHERE char *PgpV3Language; -WHERE char *PgpV3Pubring; -WHERE char *PgpV3Secring; +WHERE char *PgpSignAs; +WHERE char *PgpSignMicalg; +WHERE short PgpTimeout; +WHERE char *PgpEntryFormat; -WHERE char *PgpGpg; -#if 0 -WHERE char *PgpGpgLanguage; -WHERE char *PgpGpgPubring; -WHERE char *PgpGpgSecring; -#else -WHERE char *PgpGpgDummy; -#endif -WHERE char *PgpSendVersion; -WHERE char *PgpReceiveVersion; -WHERE char *PgpKeyVersion; -WHERE char *PgpDefaultVersion; +/* The command formats */ -WHERE char *PgpSignAs; -WHERE char *PgpSignMicalg; +WHERE char *PgpDecodeCommand; +WHERE char *PgpVerifyCommand; +WHERE char *PgpDecryptCommand; +WHERE char *PgpSignCommand; +WHERE char *PgpEncryptSignCommand; +WHERE char *PgpEncryptOnlyCommand; +WHERE char *PgpImportCommand; +WHERE char *PgpExportCommand; +WHERE char *PgpVerifyKeyCommand; +WHERE char *PgpListSecringCommand; +WHERE char *PgpListPubringCommand; -WHERE short PgpTimeout; -WHERE char *PgpEntryFormat; +/* prototypes */ BODY *pgp_decrypt_part (BODY *, STATE *, FILE *); BODY *pgp_make_key_attachment (char *); @@ -175,8 +50,6 @@ BODY *pgp_make_key_attachment (char *); char *_pgp_keyid (pgp_key_t *); char *pgp_keyid (pgp_key_t *); -const char *pgp_pkalg_to_mic (const char *); -const char *pgp_pkalgbytype (unsigned char); int mutt_check_pgp (HEADER * h); int mutt_is_application_pgp (BODY *); @@ -187,203 +60,52 @@ int pgp_decrypt_mime (FILE *, FILE **, BODY *, BODY **); int pgp_get_keys (HEADER *, char **); int pgp_protect (HEADER *, char *); int pgp_query (BODY *); -int pgp_string_matches_hint (const char *s, LIST * hints); +/* int pgp_string_matches_hint (const char *s, LIST * hints); */ int pgp_valid_passphrase (void); -pgp_key_t *gpg_get_candidates (struct pgp_vinfo *, pgp_ring_t, LIST *); -pgp_key_t *pgp_ask_for_key (struct pgp_vinfo *, char *, char *, short, pgp_ring_t); -pgp_key_t *pgp_get_candidates (struct pgp_vinfo *, pgp_ring_t, LIST *); -pgp_key_t *pgp_getkeybyaddr (struct pgp_vinfo *pgp, ADDRESS *, short, pgp_ring_t); -pgp_key_t *pgp_getkeybystr (struct pgp_vinfo *pgp, char *, short, pgp_ring_t); -pgp_key_t *pgp_remove_key (pgp_key_t **, pgp_key_t *); - -pgp_uid_t *pgp_copy_uids (pgp_uid_t *, pgp_key_t *); - -short pgp_canencrypt (unsigned char); -short pgp_cansign (unsigned char); -short pgp_get_abilities (unsigned char); - -struct pgp_vinfo *pgp_get_vinfo (enum pgp_ops); +/* pgp_key_t *gpg_get_candidates (struct pgp_vinfo *, pgp_ring_t, LIST *); */ +pgp_key_t *pgp_ask_for_key (char *, char *, short, pgp_ring_t); +pgp_key_t *pgp_get_candidates (pgp_ring_t, LIST *); +pgp_key_t *pgp_getkeybyaddr (ADDRESS *, short, pgp_ring_t); +pgp_key_t *pgp_getkeybystr (char *, short, pgp_ring_t); void mutt_forget_passphrase (void); void pgp_application_pgp_handler (BODY *, STATE *); void pgp_encrypted_handler (BODY *, STATE *); void pgp_extract_keys_from_attachment_list (FILE * fp, int tag, BODY * top); void pgp_extract_keys_from_messages (HEADER * hdr); -void pgp_free_key (pgp_key_t **kpp); void pgp_signed_handler (BODY *, STATE *); void pgp_void_passphrase (void); -#define pgp_secring(a) pgp_getring(a, 0) -#define pgp_pubring(a) pgp_getring(a, 1) - -/* PGP V2 prototypes */ - - -pid_t pgp_v2_invoke_decode (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, int); - -pid_t pgp_v2_invoke_verify (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, const char *); - - -pid_t pgp_v2_invoke_decrypt (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -pid_t pgp_v2_invoke_sign (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -pid_t pgp_v2_invoke_encrypt (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, const char *, int); - -void pgp_v2_invoke_import (struct pgp_vinfo *, const char *); - -pid_t pgp_v2_invoke_export (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -pid_t pgp_v2_invoke_verify_key (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -/* PGP V3 prototypes */ - -pid_t pgp_v3_invoke_decode (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, int); - -pid_t pgp_v3_invoke_verify (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, const char *); - - -pid_t pgp_v3_invoke_decrypt (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -pid_t pgp_v3_invoke_sign (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -pid_t pgp_v3_invoke_encrypt (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, const char *, int); - -void pgp_v3_invoke_import (struct pgp_vinfo *, const char *); - -pid_t pgp_v3_invoke_export (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -pid_t pgp_v3_invoke_verify_key (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -/* GNU Privacy Guard Prototypes */ - -pid_t pgp_gpg_invoke_decode (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, int); - -pid_t pgp_gpg_invoke_verify (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, const char *); - - -pid_t pgp_gpg_invoke_decrypt (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -pid_t pgp_gpg_invoke_sign (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -pid_t pgp_gpg_invoke_encrypt (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, const char *, int); - -void pgp_gpg_invoke_import (struct pgp_vinfo *, const char *); - -pid_t pgp_gpg_invoke_export (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -pid_t pgp_gpg_invoke_verify_key (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - - - - -#if 0 - -/* use these as templates for your own prototypes */ - - -pid_t pgp_VERSION_invoke_decode (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, int); - -pid_t pgp_VERSION_invoke_verify (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, const char *); - - -pid_t pgp_VERSION_invoke_decrypt (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -pid_t pgp_VERSION_invoke_sign (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); - -pid_t pgp_VERSION_invoke_encrypt (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *, const char *, int); - -void pgp_VERSION_invoke_import (struct pgp_vinfo *, const char *); -pid_t pgp_VERSION_invoke_export (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); -pid_t pgp_VERSION_invoke_verify_key (struct pgp_vinfo *, - FILE **, FILE **, FILE **, - int, int, int, - const char *); +/* The PGP invocation interface - not really beautiful. */ + +pid_t pgp_invoke_decode (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *fname, short need_passphrase); +pid_t pgp_invoke_verify (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *fname, const char *sig_fname); +pid_t pgp_invoke_decrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *fname); +pid_t pgp_invoke_sign (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *fname); +pid_t pgp_invoke_encrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *fname, const char *uids, int sign); +void pgp_invoke_import (const char *fname); +pid_t pgp_invoke_export (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *uids); +pid_t pgp_invoke_verify_key (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *uids); +pid_t pgp_invoke_list_keys (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + pgp_ring_t keyring, LIST *hints); -#endif #endif /* _PGPPATH */ diff --git a/pgpewrap b/pgpewrap new file mode 100755 index 00000000..2f3a21c2 --- /dev/null +++ b/pgpewrap @@ -0,0 +1,20 @@ +#!/bin/sh -- + +cmd=$1 +pfx="" + +die() { + echo "Command line usage: $0 [flags] -- prefix [recipients]" >& 2 + exit 1 +} + +while shift && test -n "$1" ; do + if test "$1" = "--" ; then + shift || die + pfx="$1" + shift || die + fi + cmd="$cmd $pfx $1" +done + +exec $cmd diff --git a/pgpinvoke.c b/pgpinvoke.c index ccc7d494..4af8b933 100644 --- a/pgpinvoke.c +++ b/pgpinvoke.c @@ -1,21 +1,28 @@ /* * Copyright (C) 1997-1999 Thomas Roessler * - * 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. */ +/* This file contains the new pgp invocation code. Note that this + * is almost entirely format based. + */ + #include #include #include @@ -25,570 +32,249 @@ #include "mutt.h" #include "pgp.h" -/******************************************************************* - * - * PGP V2 Invocation stuff - * - *******************************************************************/ - -pid_t pgp_v2_invoke_decode(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname, int need_passphrase) -{ - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), "%scat %s%s | " - "%s +language=%s +pubring=%s +secring=%s +verbose=0 +batchmode -f", - need_passphrase ? "PGPPASSFD=0; export PGPPASSFD; " : "", - need_passphrase ? "- " : "", - _fname, - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring)); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} - -pid_t pgp_v2_invoke_verify(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *signedstuff, const char *sigfile) -{ - char _sig[_POSIX_PATH_MAX + SHORT_STRING]; - char _signed[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_sig, sizeof (_sig), sigfile); - mutt_quote_filename (_signed, sizeof (_signed), signedstuff); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), - "%s +language=%s +pubring=%s +secring=%s +batchmode +verbose=0 %s %s", - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), - NONULL (secring), _sig, _signed); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} - -pid_t pgp_v2_invoke_decrypt(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname) -{ - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), - "PGPPASSFD=0; export PGPPASSFD; cat - %s | %s +language=%s +pubring=%s +secring=%s " - "+verbose=0 +batchmode -f", - _fname, NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring)); - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} - -pid_t pgp_v2_invoke_sign(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname) -{ - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), - "PGPPASSFD=0; export PGPPASSFD; cat - %s | %s " - "+language=%s +pubring=%s +secring=%s +verbose=0 +batchmode -abfst %s %s", - _fname, NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), - PgpSignAs ? "-u" : "", - PgpSignAs ? PgpSignAs : ""); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} -pid_t pgp_v2_invoke_encrypt(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname, const char *uids, int sign) +/* + * The actual command line formatter. + */ + +struct pgp_command_context { + short need_passphrase; /* %p */ + const char *fname; /* %f */ + const char *sig_fname; /* %s */ + const char *signas; /* %a */ + const char *ids; /* %r */ +}; + + +const char *_mutt_fmt_pgp_command (char *dest, + size_t destlen, + char op, + const char *src, + const char *prefix, + const char *ifstring, + const char *elsestring, + unsigned long data, + format_flag flags) { - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), - "%scat %s%s | %s +language=%s +pubring=%s +secring=%s +verbose=0 %s +batchmode -aeft%s %s%s %s", - sign ? "PGPPASSFD=0; export PGPPASSFD; " : "", - sign ? "- " : "", - _fname, - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), - option(OPTPGPENCRYPTSELF) ? "+encrypttoself" : "", - sign ? "s" : "", - sign && PgpSignAs ? "-u " : "", - sign && PgpSignAs ? PgpSignAs : "", - uids); - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); + char fmt[16]; + struct pgp_command_context *cctx = (struct pgp_command_context *) data; + int optional = (flags & M_FORMAT_OPTIONAL); + + switch (op) + { + case 'r': + { + if (!optional) + { + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, NONULL (cctx->ids)); + } + else if (!cctx->ids) + optional = 0; + break; + } + + case 'a': + { + if (!optional) + { + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, NONULL (cctx->signas)); + } + else if (!cctx->signas) + optional = 0; + break; + } + + case 's': + { + if (!optional) + { + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, NONULL (cctx->sig_fname)); + } + else if (!cctx->sig_fname) + optional = 0; + break; + } + + case 'f': + { + if (!optional) + { + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, NONULL (cctx->fname)); + } + else if (!cctx->fname) + optional = 0; + break; + } + + case 'p': + { + if (!optional) + { + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, cctx->need_passphrase ? "PGPPASSFD=0" : ""); + } + else if (!cctx->need_passphrase) + optional = 0; + break; + } + } + + if (optional) + mutt_FormatString (dest, destlen, ifstring, mutt_attach_fmt, data, 0); + else if (flags & M_FORMAT_OPTIONAL) + mutt_FormatString (dest, destlen, elsestring, mutt_attach_fmt, data, 0); + + return (src); } -void pgp_v2_invoke_import(struct pgp_vinfo *pgp, const char *fname) +void mutt_pgp_command (char *d, size_t dlen, struct pgp_command_context *cctx, const char *fmt) { - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), "%s +language=%s +pubring=%s +secring=%s -ka %s", - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), - NONULL (secring), _fname); - mutt_system(cmd); + mutt_FormatString (d, dlen, NONULL (fmt), _mutt_fmt_pgp_command, (unsigned long) cctx, 0); + dprint (2, (debugfile, "mutt_pgp_command: %s\n", d)); } -pid_t pgp_v2_invoke_export(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, const char *id) +/* + * Glue. + */ + + +static pid_t pgp_invoke (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + short need_passphrase, + const char *fname, + const char *sig_fname, + const char *signas, + const char *ids, + const char *format) { + struct pgp_command_context cctx; char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), "%s -kxaf +language=%s +pubring=%s +secring=%s 0x%8s", - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), id); - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, + + memset (&cctx, 0, sizeof (cctx)); + + cctx.need_passphrase = need_passphrase; + cctx.fname = fname; + cctx.sig_fname = sig_fname; + cctx.signas = signas; + cctx.ids = ids; + + mutt_pgp_command (cmd, sizeof (cmd), &cctx, format); + + return mutt_create_filter_fd (cmd, pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd); } -pid_t pgp_v2_invoke_verify_key(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, const char *id) -{ - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - snprintf(cmd, sizeof(cmd), "%s +language=%s +pubring=%s +secring=%s +batchmode -kcc 0x%8s", - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), id); - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} - -/******************************************************************* - * - * PGP V3 Invocation stuff +/* + * The exported interface. * - *******************************************************************/ - -pid_t pgp_v3_invoke_decode(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname, int need_passphrase) -{ - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), "%scat %s%s | " - "%sv +language=%s +pubring=%s +secring=%s +verbose=0 +batchmode -f " - "--OutputInformationFD=2", - need_passphrase ? "PGPPASSFD=0; export PGPPASSFD; " : "", - need_passphrase ? "- " : "", - _fname, - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring)); - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} - -pid_t pgp_v3_invoke_verify(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *signedstuff, const char *sigfile) -{ - char _sig[_POSIX_PATH_MAX + SHORT_STRING]; - char _sign[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_sig, sizeof (_sig), sigfile); - mutt_quote_filename (_sign, sizeof (_sign), signedstuff); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), - "%sv +language=%s +pubring=%s +secring=%s --OutputInformationFD=1 +batchmode +verbose=0 %s %s", - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), - _sig, _sign); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} - -pid_t pgp_v3_invoke_encrypt(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname, const char *uids, int sign) -{ - char *cp; - char *keylist; - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - char tmpcmd[HUGE_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), - "%scat %s%s | %se +language=%s +pubring=%s +secring=%s +verbose=0 %s +batchmode +nobatchinvalidkeys=off -aft%s %s%s", - sign ? "PGPPASSFD=0; export PGPPASSFD; " : "", - sign ? "- " : "", - _fname, - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), - option(OPTPGPENCRYPTSELF) ? "+encrypttoself" : "", - sign ? "s" : "", - sign && PgpSignAs ? "-u " : "", - sign && PgpSignAs ? PgpSignAs : ""); - - keylist = safe_strdup(uids); + * This is historic and may be removed at some point. + * + */ - for(cp = strtok(keylist, " "); cp ; cp = strtok(NULL, " ")) - { - snprintf(tmpcmd, sizeof(tmpcmd), "%s -r %s", - cmd, cp); - strcpy(cmd, tmpcmd); - } - safe_free((void **) &keylist); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} -pid_t pgp_v3_invoke_decrypt(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname) +pid_t pgp_invoke_decode (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *fname, short need_passphrase) { - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), - "PGPPASSFD=0; export PGPPASSFD; cat - %s | %sv +language=%s +pubring=%s +secring=%s " - "+verbose=0 +batchmode -f --OutputInformationFD=2", - _fname, NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring)); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); + return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, + need_passphrase, fname, NULL, NULL, NULL, + PgpDecodeCommand); } -pid_t pgp_v3_invoke_sign(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, +pid_t pgp_invoke_verify (FILE **pgpin, FILE **pgpout, FILE **pgperr, int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname) -{ - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), - "PGPPASSFD=0; export PGPPASSFD; cat - %s | %ss " - "+language=%s +pubring=%s +secring=%s +verbose=0 -abft %s %s", - _fname, NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), - PgpSignAs ? "-u" : "", - PgpSignAs ? PgpSignAs : ""); - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} -void pgp_v3_invoke_import(struct pgp_vinfo *pgp, const char *fname) + const char *fname, const char *sig_fname) { - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), "%sk +language=%s +pubring=%s +secring=%s -a --OutputInformationFD=1 %s", - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), _fname); - mutt_system(cmd); + return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, + 0, fname, sig_fname, NULL, NULL, PgpVerifyCommand); } -pid_t pgp_v3_invoke_export(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, const char *id) +pid_t pgp_invoke_decrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *fname) { - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), "%sk -xa +language=%s +pubring=%s +secring=%s --OutputInformationFD=1 0x%8s", - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), id); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); + return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, + 1, fname, NULL, NULL, NULL, PgpDecryptCommand); } -pid_t pgp_v3_invoke_verify_key(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, const char *id) +pid_t pgp_invoke_sign (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *fname) { - char cmd[HUGE_STRING]; - char pubring[_POSIX_PATH_MAX + SHORT_STRING]; - char secring[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring); - mutt_quote_filename (secring, sizeof (secring), *pgp->secring); - - snprintf(cmd, sizeof(cmd), "%sk +language=%s +pubring=%s +secring=%s +batchmode -c --OutputInformationFD=1 0x%8s", - NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), id); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); + return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, + 1, fname, NULL, PgpSignAs, NULL, PgpSignCommand); } -/******************************************************************* - * - * GNU Privacy Guard invocation stuff - * - * Credits go to Werner Koch for sending me the code on which this - * is based. - * - *******************************************************************/ -pid_t pgp_gpg_invoke_decode(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname, int need_passphrase) +pid_t pgp_invoke_encrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *fname, const char *uids, int sign) { - char cmd[HUGE_STRING]; - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - - snprintf(cmd, sizeof(cmd), - "%s%s --no-verbose --batch -o - %s", - NONULL(*pgp->binary), need_passphrase? " --passphrase-fd 0":"", - _fname); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} - -pid_t pgp_gpg_invoke_verify(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *signedstuff, const char *sigfile) -{ - char _sig[_POSIX_PATH_MAX + SHORT_STRING]; - char _sign[_POSIX_PATH_MAX + SHORT_STRING]; - char cmd[HUGE_STRING]; - - mutt_quote_filename (_sig, sizeof (_sig), sigfile); - mutt_quote_filename (_sign, sizeof (_sign), signedstuff); - - snprintf(cmd, sizeof(cmd), - "%s --no-verbose --batch -o - " - "--verify %s %s", - NONULL(*pgp->binary), _sig, _sign); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); + if (sign) + return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, + 1, fname, NULL, PgpSignAs, uids, + PgpEncryptSignCommand); + else + return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, + 0, fname, NULL, NULL, uids, + PgpEncryptOnlyCommand); } -pid_t pgp_gpg_invoke_decrypt(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname) +void pgp_invoke_import (const char *fname) { char _fname[_POSIX_PATH_MAX + SHORT_STRING]; char cmd[HUGE_STRING]; - + struct pgp_command_context cctx; + + memset (&cctx, 0, sizeof (cctx)); + mutt_quote_filename (_fname, sizeof (_fname), fname); - - snprintf(cmd, sizeof(cmd), - "%s --passphrase-fd 0 --no-verbose --batch -o - " - "--decrypt %s", - NONULL(*pgp->binary), _fname); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); + cctx.fname = _fname; + + mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpImportCommand); + mutt_system (cmd); } -static char *gpg_digalg(void) +pid_t pgp_invoke_export (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *uids) { - static char digalg[STRING]; - if(PgpSignMicalg && !mutt_strncasecmp(PgpSignMicalg, "pgp-", 4)) - strfcpy(digalg, PgpSignMicalg + 4, sizeof(digalg)); - else - { - /* We use md5 here as the default value as it's the good - * old default value for PGP and will be used in the - * message's headers. - */ - - strcpy(digalg, "md5"); - } - return digalg; + return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, + 0, NULL, NULL, NULL, uids, + PgpExportCommand); } -pid_t pgp_gpg_invoke_sign(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname) +pid_t pgp_invoke_verify_key (FILE **pgpin, FILE **pgpout, FILE **pgperr, + int pgpinfd, int pgpoutfd, int pgperrfd, + const char *uids) { - char cmd[HUGE_STRING]; - - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - - snprintf(cmd, sizeof(cmd), - "%s --no-verbose --batch -o - " - "--passphrase-fd 0 --digest-algo %s " - "--detach-sign --textmode --armor %s%s %s", - NONULL(*pgp->binary), - gpg_digalg(), - PgpSignAs? "-u " : "", - PgpSignAs? PgpSignAs : "", _fname); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); + return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, + 0, NULL, NULL, NULL, uids, + PgpVerifyKeyCommand); } -pid_t pgp_gpg_invoke_encrypt(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, - const char *fname, const char *uids, int sign) +pid_t pgp_invoke_list_keys (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; - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - - snprintf(cmd, sizeof(cmd), - "%s%s --no-verbose -v --batch -o - " - "--digest-algo %s " - "--encrypt%s --textmode --armor --always-trust %s%s", - NONULL(*pgp->binary), - sign? " --passphrase-fd 0":"", - gpg_digalg(), - sign? " --sign":"", - PgpSignAs? "-u " : "", - PgpSignAs? PgpSignAs : "" ); + char uids[HUGE_STRING]; + char tmpuids[HUGE_STRING]; - keylist = safe_strdup(uids); - for(cp = strtok(keylist, " "); cp ; cp = strtok(NULL, " ")) + *uids = '\0'; + + for (; hints; hints = hints->next) { - snprintf(tmpcmd, sizeof(tmpcmd), "%s -r %s", - cmd, cp); - strcpy(cmd, tmpcmd); + snprintf (tmpuids, sizeof (tmpuids), "%s %s", uids, (char *) hints->data); + strcpy (uids, tmpuids); } - safe_free((void **) &keylist); - - snprintf(tmpcmd, sizeof(tmpcmd), "%s %s", cmd, _fname); - strcpy(cmd, tmpcmd); - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} - -void pgp_gpg_invoke_import(struct pgp_vinfo *pgp, const char *fname) -{ - char cmd[HUGE_STRING]; - char _fname[_POSIX_PATH_MAX + SHORT_STRING]; - - mutt_quote_filename (_fname, sizeof (_fname), fname); - - snprintf(cmd, sizeof(cmd), "%sm --no-verbose --import -v %s", - NONULL(*pgp->binary), _fname); - - mutt_system(cmd); -} - -pid_t pgp_gpg_invoke_export(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, const char *id) -{ - char cmd[HUGE_STRING]; - - snprintf(cmd, sizeof(cmd), "%sm --no-verbose --export --armor 0x%8s", - NONULL(*pgp->binary), id); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); -} - -pid_t pgp_gpg_invoke_verify_key(struct pgp_vinfo *pgp, - FILE **pgpin, FILE **pgpout, FILE **pgperr, - int pgpinfd, int pgpoutfd, int pgperrfd, const char *id) -{ - char cmd[HUGE_STRING]; - - snprintf(cmd, sizeof(cmd), - "%sm --no-verbose --batch --fingerprint --check-sigs %s%s", - NONULL(*pgp->binary), (mutt_strlen(id)==8 || mutt_strlen(id)==16)? "0x":"", id ); - - return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, - pgpinfd, pgpoutfd, pgperrfd); + return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd, + 0, NULL, NULL, NULL, uids, + keyring == PGP_SECRING ? PgpListSecringCommand : + PgpListPubringCommand); } diff --git a/pgpkey.c b/pgpkey.c index 869fef00..b1c12a95 100644 --- a/pgpkey.c +++ b/pgpkey.c @@ -381,15 +381,14 @@ static int pgp_compare_trust (const void *a, const void *b) : _pgp_compare_trust (a, b)); } -static pgp_key_t *pgp_select_key (struct pgp_vinfo *pgp, - pgp_key_t *keys, +static pgp_key_t *pgp_select_key (pgp_key_t *keys, ADDRESS * p, const char *s) { int keymax; pgp_uid_t **KeyTable; MUTTMENU *menu; int i, done = 0; - char helpstr[SHORT_STRING], buf[LONG_STRING]; + char helpstr[SHORT_STRING], buf[LONG_STRING], tmpbuf[STRING]; char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX]; FILE *fp, *devnull; pid_t thepid; @@ -490,9 +489,10 @@ static pgp_key_t *pgp_select_key (struct pgp_vinfo *pgp, mutt_message _("Invoking PGP..."); - if ((thepid = pgp->invoke_verify_key (pgp, NULL, NULL, NULL, -1, - fileno (fp), fileno (devnull), - pgp_keyid (pgp_principal_key (KeyTable[menu->current]->parent)))) == -1) + snprintf (tmpbuf, sizeof (tmpbuf), "0x%s", pgp_keyid (pgp_principal_key (KeyTable[menu->current]->parent))); + + if ((thepid = pgp_invoke_verify_key (NULL, NULL, NULL, -1, + fileno (fp), fileno (devnull), tmpbuf)) == -1) { mutt_perror _("Can't create filter"); unlink (tempfile); @@ -588,7 +588,7 @@ static pgp_key_t *pgp_select_key (struct pgp_vinfo *pgp, return (kp); } -pgp_key_t *pgp_ask_for_key (struct pgp_vinfo *pgp, char *tag, char *whatfor, +pgp_key_t *pgp_ask_for_key (char *tag, char *whatfor, short abilities, pgp_ring_t keyring) { pgp_key_t *key; @@ -631,7 +631,7 @@ pgp_key_t *pgp_ask_for_key (struct pgp_vinfo *pgp, char *tag, char *whatfor, } } - if ((key = pgp_getkeybystr (pgp, resp, abilities, keyring))) + if ((key = pgp_getkeybystr (resp, abilities, keyring))) return key; BEEP (); @@ -645,25 +645,19 @@ BODY *pgp_make_key_attachment (char *tempf) { BODY *att; char buff[LONG_STRING]; - char tempfb[_POSIX_PATH_MAX]; - char *id; + char tempfb[_POSIX_PATH_MAX], tmp[STRING]; FILE *tempfp; FILE *devnull; struct stat sb; pid_t thepid; pgp_key_t *key; - struct pgp_vinfo *pgp = pgp_get_vinfo (PGP_EXPORT); - - if (!pgp) - return NULL; - unset_option (OPTPGPCHECKTRUST); - key = pgp_ask_for_key (pgp, _("Please enter the key ID: "), NULL, 0, PGP_PUBRING); + key = pgp_ask_for_key (_("Please enter the key ID: "), NULL, 0, PGP_PUBRING); if (!key) return NULL; - id = safe_strdup (pgp_keyid (pgp_principal_key(key))); + snprintf (tmp, sizeof (tmp), "0x%s", pgp_keyid (pgp_principal_key (key))); pgp_free_key (&key); if (!tempf) @@ -675,14 +669,12 @@ BODY *pgp_make_key_attachment (char *tempf) if ((tempfp = safe_fopen (tempf, tempf == tempfb ? "w" : "a")) == NULL) { mutt_perror _("Can't create temporary file"); - safe_free ((void **) &id); return NULL; } if ((devnull = fopen ("/dev/null", "w")) == NULL) { mutt_perror _("Can't open /dev/null"); - safe_free ((void **) &id); fclose (tempfp); if (tempf == tempfb) unlink (tempf); @@ -690,16 +682,16 @@ BODY *pgp_make_key_attachment (char *tempf) } mutt_message _("Invoking pgp..."); + if ((thepid = - pgp->invoke_export (pgp, NULL, NULL, NULL, -1, - fileno (tempfp), fileno (devnull), id)) == -1) + pgp_invoke_export (NULL, NULL, NULL, -1, + fileno (tempfp), fileno (devnull), tmp)) == -1) { mutt_perror _("Can't create filter"); unlink (tempf); fclose (tempfp); fclose (devnull); - safe_free ((void **) &id); return NULL; } @@ -713,14 +705,13 @@ BODY *pgp_make_key_attachment (char *tempf) att->unlink = 1; att->type = TYPEAPPLICATION; att->subtype = safe_strdup ("pgp-keys"); - snprintf (buff, sizeof (buff), _("PGP Key 0x%s."), id); + snprintf (buff, sizeof (buff), _("PGP Key %s."), tmp); att->description = safe_strdup (buff); mutt_update_encoding (att); stat (tempf, &sb); att->length = sb.st_size; - safe_free ((void **) &id); return att; } @@ -741,8 +732,7 @@ static LIST *pgp_add_string_to_hints (LIST *hints, const char *str) } -pgp_key_t *pgp_getkeybyaddr (struct pgp_vinfo * pgp, - ADDRESS * a, short abilities, pgp_ring_t keyring) +pgp_key_t *pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring) { ADDRESS *r, *p; LIST *hints = NULL; @@ -760,7 +750,7 @@ pgp_key_t *pgp_getkeybyaddr (struct pgp_vinfo * pgp, hints = pgp_add_string_to_hints (hints, a->personal); mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox); - keys = pgp->get_candidates (pgp, keyring, hints); + keys = pgp_get_candidates (keyring, hints); mutt_free_list (&hints); @@ -850,7 +840,7 @@ pgp_key_t *pgp_getkeybyaddr (struct pgp_vinfo * pgp, if (matches->next || weak) { /* query for which key the user wants */ - k = pgp_select_key (pgp, matches, a, NULL); + k = pgp_select_key (matches, a, NULL); if (k) pgp_remove_key (&matches, k); @@ -865,8 +855,7 @@ pgp_key_t *pgp_getkeybyaddr (struct pgp_vinfo * pgp, return NULL; } -pgp_key_t *pgp_getkeybystr (struct pgp_vinfo * pgp, - char *p, short abilities, pgp_ring_t keyring) +pgp_key_t *pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring) { LIST *hints = NULL; pgp_key_t *keys; @@ -879,7 +868,7 @@ pgp_key_t *pgp_getkeybystr (struct pgp_vinfo * pgp, mutt_message (_("Looking for keys matching \"%s\"..."), p); hints = pgp_add_string_to_hints (hints, p); - keys = pgp->get_candidates (pgp, keyring, hints); + keys = pgp_get_candidates (keyring, hints); mutt_free_list (&hints); if (!keys) @@ -936,7 +925,7 @@ pgp_key_t *pgp_getkeybystr (struct pgp_vinfo * pgp, if (matches) { - k = pgp_select_key (pgp, matches, NULL, p); + k = pgp_select_key (matches, NULL, p); if (k) pgp_remove_key (&matches, k); diff --git a/pgplib.c b/pgplib.c new file mode 100644 index 00000000..40e395e2 --- /dev/null +++ b/pgplib.c @@ -0,0 +1,265 @@ +/* + * Copyright (C) 1997-1999 Thomas Roessler + * + * 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. + * + * 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. + */ + +/* Generally useful, pgp-related functions. */ + +#include +#include +#include +#include +#include + +#include "lib.h" +#include "pgplib.h" + +const char *pgp_pkalgbytype (unsigned char 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"; + } +} + + +static struct +{ + char *pkalg; + char *micalg; +} +pktomic[] = +{ + { + "RSA", "pgp-md5" + } + , + { + "ElG", "pgp-rmd160" + } + , + { + "DSA", "pgp-sha1" + } + , + { + NULL, "x-unknown" + } +}; + + +const char *pgp_pkalg_to_mic (const char *alg) +{ + int i; + + for (i = 0; pktomic[i].pkalg; i++) + { + if (!mutt_strcasecmp (pktomic[i].pkalg, alg)) + break; + } + + return pktomic[i].micalg; +} + + +/* unused */ + +#if 0 + +static const char *hashalgbytype (unsigned char type) +{ + switch (type) + { + 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) +{ + switch (type) + { + case 1: + case 2: + case 16: + case 20: + return 1; + default: + return 0; + } +} + +short pgp_cansign (unsigned char type) +{ + switch (type) + { + case 1: + case 3: + 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) +{ + return (pgp_canencrypt (type) << 1) | pgp_cansign (type); +} + +void pgp_free_uid (pgp_uid_t ** upp) +{ + pgp_uid_t *up, *q; + + if (!upp || !*upp) + return; + for (up = *upp; up; up = q) + { + q = up->next; + safe_free ((void **) &up->addr); + safe_free ((void **) &up); + } + + *upp = NULL; +} + +pgp_uid_t *pgp_copy_uids (pgp_uid_t *up, pgp_key_t *parent) +{ + pgp_uid_t *l = NULL; + pgp_uid_t **lp = &l; + + for (; up; up = up->next) + { + *lp = safe_calloc (1, sizeof (pgp_uid_t)); + (*lp)->trust = up->trust; + (*lp)->addr = safe_strdup (up->addr); + (*lp)->parent = parent; + lp = &(*lp)->next; + } + + return l; +} + +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); +} + +pgp_key_t *pgp_remove_key (pgp_key_t ** klist, pgp_key_t * key) +{ + 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; +} + diff --git a/pgplib.h b/pgplib.h new file mode 100644 index 00000000..2f4c5bfd --- /dev/null +++ b/pgplib.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 1996,1997 Michael R. Elkins + * Copyright (C) 1999 Thoms Roessler + * + * 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. + * + * 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. + */ + +#ifdef _PGPPATH + +#define PGPENCRYPT 1 +#define PGPSIGN 2 +#define PGPKEY 4 + +#define KEYFLAG_CANSIGN (1 << 0) +#define KEYFLAG_CANENCRYPT (1 << 1) +#define KEYFLAG_SECRET (1 << 7) +#define KEYFLAG_EXPIRED (1 << 8) +#define KEYFLAG_REVOKED (1 << 9) +#define KEYFLAG_DISABLED (1 << 10) +#define KEYFLAG_SUBKEY (1 << 11) +#define KEYFLAG_CRITICAL (1 << 12) +#define KEYFLAG_PREFER_ENCRYPTION (1 << 13) +#define KEYFLAG_PREFER_SIGNING (1 << 14) + +#define KEYFLAG_CANTUSE (KEYFLAG_DISABLED|KEYFLAG_REVOKED|KEYFLAG_EXPIRED) +#define KEYFLAG_RESTRICTIONS (KEYFLAG_CANTUSE|KEYFLAG_CRITICAL) + +#define KEYFLAG_ABILITIES (KEYFLAG_CANSIGN|KEYFLAG_CANENCRYPT|KEYFLAG_PREFER_ENCRYPTION|KEYFLAG_PREFER_SIGNING) + +typedef struct pgp_keyinfo +{ + char *keyid; + struct pgp_uid *address; + int flags; + short keylen; + time_t gen_time; + int numalg; + const char *algorithm; + struct pgp_keyinfo *parent; + struct pgp_keyinfo *next; +} +pgp_key_t; + +typedef struct pgp_uid +{ + char *addr; + short trust; + struct pgp_keyinfo *parent; + struct pgp_uid *next; +} +pgp_uid_t; + +enum pgp_version +{ + PGP_V2, + PGP_V3, + PGP_GPG, + PGP_UNKNOWN +}; + +enum pgp_ring +{ + PGP_PUBRING, + PGP_SECRING +}; + +typedef enum pgp_ring pgp_ring_t; + +/* prototypes */ + +const char *pgp_pkalg_to_mic (const char *); +const char *pgp_pkalgbytype (unsigned char); + +pgp_key_t *pgp_remove_key (pgp_key_t **, pgp_key_t *); +pgp_uid_t *pgp_copy_uids (pgp_uid_t *, pgp_key_t *); + +short pgp_canencrypt (unsigned char); +short pgp_cansign (unsigned char); +short pgp_get_abilities (unsigned char); + +void pgp_free_key (pgp_key_t **kpp); + +#define pgp_new_keyinfo() safe_calloc (sizeof (pgp_key_t), 1) + +#endif /* _PGPPATH */ diff --git a/pgppubring.c b/pgppubring.c index ad001e78..ff3c27f7 100644 --- a/pgppubring.c +++ b/pgppubring.c @@ -19,6 +19,23 @@ * 02139, USA. */ +/* + * This is a "simple" PGP key ring dumper. + * + * The output format is supposed to be compatible to the one GnuPG + * emits and Mutt expects. + * + * Note that the code of this program could be considerably less + * complex, but most of it was taken from mutt's second generation + * key ring parser. + * + * You can actually use this to put together some fairly general + * PGP key management applications. + * + */ + + +#include "config.h" #include #include @@ -26,16 +43,54 @@ #include #include +#ifdef HAVE_GETOPT_H +# include +#endif + #include "sha.h" -#include "mutt.h" -#include "pgp.h" -#include "charset.h" +#include "lib.h" +#include "pgplib.h" #define CHUNKSIZE 1024 static unsigned char *pbuf = NULL; static size_t plen = 0; +static void pgpring_find_candidates (char *ringfile, const char *hints[], int nhints); +static void pgpring_dump_keyblock (pgp_key_t *p); + +int main (int argc, char * const argv[]) +{ + int c; + + char kring[_POSIX_PATH_MAX]; + char *pgppath; + + if ((pgppath = getenv ("PGPPATH"))) + snprintf (kring, sizeof (kring), "%s/%s", pgppath, "pubring.pgp"); + else + *kring = '\0'; + + while ((c = getopt (argc, argv, "k:")) != EOF) + { + if (c == 'k') + strfcpy (kring, optarg, sizeof (kring)); + else + { + fprintf (stderr, "usage: %s [-k key ring] [hints]\n", + argv[0]); + exit (1); + } + } + + pgpring_find_candidates (kring, argv + optind, argc - optind); + + return 0; +} + + + + enum packet_tags { PT_RES0 = 0, /* reserved */ @@ -57,151 +112,34 @@ enum packet_tags PT_COMMENT /* Comment Packet */ }; -/* FIXME I can't find where those strings are displayed! */ -const char *pgp_packet_name[] = -{ - N_("reserved"), - N_("Encrypted Session Key"), - N_("Signature Packet"), - N_("Conventionally Encrypted Session Key Packet"), - N_("One-Pass Signature Packet"), - N_("Secret Key Packet"), - N_("Public Key Packet"), - N_("Secret Subkey Packet"), - N_("Compressed Data Packet"), - N_("Symmetrically Encrypted Data Packet"), - N_("Marker Packet"), - N_("Literal Data Packet"), - N_("Trust Packet"), - N_("Name Packet"), - N_("Subkey Packet"), - N_("Reserved"), - N_("Comment Packet") -}; - -const char *pgp_pkalgbytype (unsigned char 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"; - } -} - - -static struct -{ - char *pkalg; - char *micalg; -} -pktomic[] = -{ - { - "RSA", "pgp-md5" - } - , - { - "ElG", "pgp-rmd160" - } - , - { - "DSA", "pgp-sha1" - } - , - { - NULL, "x-unknown" - } -}; - - -const char *pgp_pkalg_to_mic (const char *alg) -{ - int i; - - for (i = 0; pktomic[i].pkalg; i++) - { - if (!mutt_strcasecmp (pktomic[i].pkalg, alg)) - break; - } - - return pktomic[i].micalg; -} - - -/* unused */ - -#if 0 - -static const char *hashalgbytype (unsigned char type) -{ - switch (type) - { - 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) -{ - switch (type) - { - case 1: - case 2: - case 16: - case 20: - return 1; - default: - return 0; - } -} - -short pgp_cansign (unsigned char type) -{ - switch (type) - { - case 1: - case 3: - case 17: - case 20: - return 1; - default: - return 0; - } -} - -/* return values: - - * 1 = sign only - * 2 = encrypt only - * 3 = both +/* + * These aren't displayed at all currently, but they may come quite + * handy for debugging strings. + * + * No need to translate them. + * */ -short pgp_get_abilities (unsigned char type) +const char *pgp_packet_name[] = { - return (pgp_canencrypt (type) << 1) | pgp_cansign (type); -} + "reserved", + "Encrypted Session Key", + "Signature Packet", + "Conventionally Encrypted Session Key Packet", + "One-Pass Signature Packet", + "Secret Key Packet", + "Public Key Packet", + "Secret Subkey Packet", + "Compressed Data Packet", + "Symmetrically Encrypted Data Packet", + "Marker Packet", + "Literal Data Packet", + "Trust Packet", + "Name Packet", + "Subkey Packet", + "Reserved", + "Comment Packet" +}; static int read_material (size_t material, size_t * used, FILE * fp) { @@ -214,7 +152,7 @@ static int read_material (size_t material, size_t * used, FILE * fp) if (!(p = realloc (pbuf, nplen))) { - mutt_perror ("realloc"); + perror ("realloc"); return -1; } plen = nplen; @@ -223,7 +161,7 @@ static int read_material (size_t material, size_t * used, FILE * fp) if (fread (pbuf + *used, 1, material, fp) < material) { - mutt_perror ("fread"); + perror ("fread"); return -1; } @@ -250,7 +188,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len) if (fread (&ctb, 1, 1, fp) < 1) { if (!feof (fp)) - mutt_perror ("fread"); + perror ("fread"); goto bail; } @@ -269,7 +207,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len) { if (fread (&b, 1, 1, fp) < 1) { - mutt_perror ("fread"); + perror ("fread"); goto bail; } @@ -284,7 +222,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len) material = (b - 192) * 256; if (fread (&b, 1, 1, fp) < 1) { - mutt_perror ("fread"); + perror ("fread"); goto bail; } material += b + 192; @@ -303,7 +241,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len) unsigned char buf[4]; if (fread (buf, 4, 1, fp) < 1) { - mutt_perror ("fread"); + perror ("fread"); goto bail; } /*assert( sizeof(material) >= 4 ); */ @@ -334,7 +272,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len) { if (fread (&b, 1, 1, fp) < 1) { - mutt_perror ("fread"); + perror ("fread"); goto bail; } @@ -358,7 +296,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len) { if (fread (&b, 1, 1, fp) < 1) { - mutt_perror ("fread"); + perror ("fread"); goto bail; } @@ -386,120 +324,6 @@ bail: return NULL; } -static pgp_key_t *pgp_new_keyinfo (void) -{ - return safe_calloc (sizeof (pgp_key_t), 1); -} - -void pgp_free_uid (pgp_uid_t ** upp) -{ - pgp_uid_t *up, *q; - - if (!upp || !*upp) - return; - for (up = *upp; up; up = q) - { - q = up->next; - safe_free ((void **) &up->addr); - safe_free ((void **) &up); - } - - *upp = NULL; -} - -pgp_uid_t *pgp_copy_uids (pgp_uid_t *up, pgp_key_t *parent) -{ - pgp_uid_t *l = NULL; - pgp_uid_t **lp = &l; - - for (; up; up = up->next) - { - *lp = safe_calloc (1, sizeof (pgp_uid_t)); - (*lp)->trust = up->trust; - (*lp)->addr = safe_strdup (up->addr); - (*lp)->parent = parent; - lp = &(*lp)->next; - } - - return l; -} - -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); -} - -pgp_key_t *pgp_remove_key (pgp_key_t ** klist, pgp_key_t * key) -{ - 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; @@ -515,7 +339,7 @@ static pgp_key_t *pgp_parse_pgp2_key (unsigned char *buff, size_t l) if (l < 12) return NULL; - p = pgp_new_keyinfo (); + p = pgp_new_keyinfo(); for (i = 0, j = 2; i < 4; i++) gen_time = (gen_time << 8) + buff[j++]; @@ -530,6 +354,7 @@ static pgp_key_t *pgp_parse_pgp2_key (unsigned char *buff, size_t l) alg = buff[j++]; + p->numalg = alg; p->algorithm = pgp_pkalgbytype (alg); p->flags |= pgp_get_abilities (alg); @@ -628,6 +453,7 @@ static pgp_key_t *pgp_parse_pgp3_key (unsigned char *buff, size_t l) alg = buff[j++]; + p->numalg = alg; p->algorithm = pgp_pkalgbytype (alg); p->flags |= pgp_get_abilities (alg); @@ -665,8 +491,6 @@ static pgp_key_t *pgp_parse_keyinfo (unsigned char *buff, size_t l) if (!buff || l < 2) return NULL; - dprint (5, (debugfile, " version: %d ", buff[1])); - switch (buff[1]) { case 2: @@ -876,8 +700,6 @@ static pgp_key_t *pgp_parse_keyblock (FILE * fp) pgp_uid_t *uid = NULL; pgp_uid_t **addr = NULL; - CHARSET *chs = mutt_get_charset (Charset); - fgetpos (fp, &pos); while (!err && (buff = pgp_read_packet (fp, &l)) != NULL) @@ -919,33 +741,32 @@ static pgp_key_t *pgp_parse_keyblock (FILE * fp) while (*addr) addr = &(*addr)->next; } } + + if (pt == PT_SECKEY || pt == PT_SUBSECKEY) + p->flags |= KEYFLAG_SECRET; + break; } case PT_SIG: { - dprint (5, (debugfile, "PT_SIG\n")); pgp_parse_sig (buff, l, p); break; } case PT_TRUST: { - dprint (5, (debugfile, "PT_TRUST: ")); if (p && (last_pt == PT_SECKEY || last_pt == PT_PUBKEY || last_pt == PT_SUBKEY || last_pt == PT_SUBSECKEY)) { if (buff[1] & 0x20) { - dprint (5, (debugfile, " disabling %s\n", p->keyid)); p->flags |= KEYFLAG_DISABLED; } } 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)); } break; } @@ -953,7 +774,6 @@ static pgp_key_t *pgp_parse_keyblock (FILE * fp) { char *chr; - dprint (5, (debugfile, "PT_NAME: ")); if (!addr) break; @@ -962,9 +782,7 @@ static pgp_key_t *pgp_parse_keyblock (FILE * fp) memcpy (chr, buff + 1, l - 1); chr[l - 1] = '\0'; - dprint (5, (debugfile, "\"%s\"\n", chr)); - mutt_decode_utf8_string (chr, chs); *addr = uid = safe_calloc (1, sizeof (pgp_uid_t)); /* XXX */ uid->addr = chr; uid->parent = p; @@ -993,28 +811,29 @@ static pgp_key_t *pgp_parse_keyblock (FILE * fp) return root; } -int pgp_string_matches_hint (const char *s, LIST * hints) +static int pgpring_string_matches_hint (const char *s, const char *hints[], int nhints) { - if (!hints) + int i; + + if (!hints || !nhints) return 1; - for (; hints; hints = hints->next) + for (i = 0; i < nhints; i++) { - if (mutt_stristr (s, (char *) hints->data) != NULL) + if (mutt_stristr (s, hints[i]) != NULL) return 1; } return 0; } -/* Go through the key ring file and look for keys with +/* + * Go through the key ring file and look for keys with * matching IDs. */ -pgp_key_t *pgp_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring, - LIST * hints) +static void pgpring_find_candidates (char *ringfile, const char *hints[], int nhints) { - char *ringfile; FILE *rfp; fpos_t pos, keypos; @@ -1022,28 +841,12 @@ pgp_key_t *pgp_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring, unsigned char pt = 0; size_t l = 0; - CHARSET *chs = mutt_get_charset (Charset); - - pgp_key_t *keys = NULL; - pgp_key_t **last = &keys; short err = 0; - - switch (keyring) - { - case PGP_PUBRING: - ringfile = *pgp->pubring; - break; - case PGP_SECRING: - ringfile = *pgp->secring; - break; - default: - return NULL; - } - + if ((rfp = fopen (ringfile, "r")) == NULL) { - mutt_perror ("fopen"); - return NULL; + perror ("fopen"); + return; } fgetpos (rfp, &pos); @@ -1066,9 +869,10 @@ pgp_key_t *pgp_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring, memcpy (tmp, buff + 1, l - 1); tmp[l - 1] = '\0'; - mutt_decode_utf8_string (tmp, chs); - if (pgp_string_matches_hint (tmp, hints)) + /* mutt_decode_utf8_string (tmp, chs); */ + + if (pgpring_string_matches_hint (tmp, hints, nhints)) { pgp_key_t *p; @@ -1076,11 +880,11 @@ pgp_key_t *pgp_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring, /* Not bailing out here would lead us into an endless loop. */ - if ((*last = pgp_parse_keyblock (rfp)) == NULL) + if ((p = pgp_parse_keyblock (rfp)) == NULL) err = 1; - - for (p = *last; p; p = p->next) - last = &p->next; + + pgpring_dump_keyblock (p); + pgp_free_key (&p); } safe_free ((void **) &tmp); @@ -1091,5 +895,86 @@ pgp_key_t *pgp_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring, fclose (rfp); - return keys; } + +static void print_userid (const char *id) +{ + for (; id && *id; id++) + { + if (*id >= ' ' && *id <= 'z' && *id != ':') + putchar (*id); + else + printf ("\\x%02x", *id); + } +} + +static char gnupg_trustletter (int t) +{ + switch (t) + { + case 1: return 'n'; + case 2: return 'm'; + case 3: return 'f'; + } + return 'q'; +} + +static void pgpring_dump_keyblock (pgp_key_t *p) +{ + pgp_uid_t *uid; + short first; + struct tm *tp; + time_t t; + + for (; p; p = p->next) + { + first = 1; + + if (p->flags & KEYFLAG_SECRET) + { + if (p->flags & KEYFLAG_SUBKEY) + printf ("ssb:"); + else + printf ("sec:"); + } + else + { + if (p->flags & KEYFLAG_SUBKEY) + printf ("sub:"); + else + printf ("pub:"); + } + + if (p->flags & KEYFLAG_REVOKED) + putchar ('r'); + if (p->flags & KEYFLAG_EXPIRED) + putchar ('e'); + + for (uid = p->address; uid; uid = uid->next, first = 0) + { + if (!first) + { + printf ("uid:%c::::::::", gnupg_trustletter (uid->trust)); + print_userid (uid->addr); + printf (":\n"); + } + else + { + if (p->flags & KEYFLAG_SECRET) + putchar ('u'); + else + putchar (gnupg_trustletter (uid->trust)); + + t = p->gen_time; + tp = gmtime (&t); + + printf (":%d:%d:%s:%04d-%02d-%02d::::", p->keylen, p->numalg, p->keyid, + 1900 + tp->tm_year, tp->tm_mon + 1, tp->tm_mday); + + print_userid (uid->addr); + printf (":\n"); + } + } + } +} +