/*
* Copyright (C) 1997-2000 Thomas Roessler <roessler@guug.de>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later
* version.
*
* This program is 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., 59 Temple Place - Suite 330,
* Boston, MA 02111, 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#endif
extern char *optarg;
extern int optind;
#include "sha1.h"
#include "lib.h"
#include "pgplib.h"
#ifdef HAVE_FGETPOS
#define FGETPOS(fp,pos) fgetpos((fp),&(pos))
#define FSETPOS(fp,pos) fsetpos((fp),&(pos))
#else
#define FGETPOS(fp,pos) pos=ftell((fp));
#define FSETPOS(fp,pos) fseek((fp),(pos),SEEK_SET)
#endif
#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;
short version = 2;
short secring = 0;
const char *_kring = NULL;
char *env_pgppath, *env_home;
char pgppath[_POSIX_PATH_MAX];
char kring[_POSIX_PATH_MAX];
while ((c = getopt (argc, argv, "25sk:")) != EOF)
{
switch (c)
{
case 'k':
{
_kring = optarg;
break;
}
case '2': case '5':
{
version = c - '0';
break;
}
case 's':
{
secring = 1;
break;
}
default:
{
fprintf (stderr, "usage: %s [-k <key ring> | [-2 | -5] [ -s]] [hints]\n",
argv[0]);
exit (1);
}
}
}
if (_kring)
strfcpy (kring, _kring, sizeof (kring));
else
{
if ((env_pgppath = getenv ("PGPPATH")))
strfcpy (pgppath, env_pgppath, sizeof (pgppath));
else if ((env_home = getenv ("HOME")))
snprintf (pgppath, sizeof (pgppath), "%s/.pgp", env_home);
else
{
fprintf (stderr, "%s: Can't determine your PGPPATH.\n", argv[0]);
exit (1);
}
if (secring)
snprintf (kring, sizeof (kring), "%s/secring.%s", pgppath, version == 2 ? "pgp" : "skr");
else
snprintf (kring, sizeof (kring), "%s/pubring.%s", pgppath, version == 2 ? "pgp" : "pkr");
}
pgpring_find_candidates (kring, (const char**) argv + optind, argc - optind);
return 0;
}
/* The actual key ring parser */
enum packet_tags
{
PT_RES0 = 0, /* reserved */
PT_ESK, /* Encrypted Session Key */
PT_SIG, /* Signature Packet */
PT_CESK, /* Conventionally Encrypted Session Key Packet */
PT_OPS, /* One-Pass Signature Packet */
PT_SECKEY, /* Secret Key Packet */
PT_PUBKEY, /* Public Key Packet */
PT_SUBSECKEY, /* Secret Subkey Packet */
PT_COMPRESSED, /* Compressed Data Packet */
PT_SKE, /* Symmetrically Encrypted Data Packet */
PT_MARKER, /* Marker Packet */
PT_LITERAL, /* Literal Data Packet */
PT_TRUST, /* Trust Packet */
PT_NAME, /* Name Packet */
PT_SUBKEY, /* Subkey Packet */
PT_RES15, /* Reserved */
PT_COMMENT /* Comment Packet */
};
/*
* These aren't displayed at all currently, but they may come quite
* handy for debugging strings.
*
* No need to translate them.
*
*/
#if 0
const char *pgp_packet_name[] =
{
"reserved",
"Encrypted Session Key",
"Signature Packet",
"Conventionally Encrypted Session Key Packet",
"One-Pass Signature Packet",
"Secret Key Packet",
"Public Key Packet",
"Secret Subkey Packet",
&qu