/*
* Copyright (C) 1997-2003 Thomas Roessler <roessler@does-not-exist.org>
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, 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.
*
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#endif
#include <errno.h>
extern char *optarg;
extern int optind;
#include "sha1.h"
#include "md5.h"
#include "lib.h"
#include "pgplib.h"
#include "pgppacket.h"
#define MD5_DIGEST_LENGTH 16
#ifdef HAVE_FGETPOS
#define FGETPOS(fp,pos) fgetpos((fp),&(pos))
#define FSETPOS(fp,pos) fsetpos((fp),&(pos))
#else
#define FGETPOS(fp,pos) pos=ftello((fp));
#define FSETPOS(fp,pos) fseeko((fp),(pos),SEEK_SET)
#endif
static short dump_signatures = 0;
static short dump_fingerprints = 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, "f25sk:S")) != EOF)
{
switch (c)
{
case 'S':
{
dump_signatures = 1;
break;
}
case 'f':
{
dump_fingerprints = 1;
break;
}
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] [-S] [-f]] [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;
}
static char *binary_fingerprint_to_string (unsigned char *buff, size_t length)
{
int i;
char *fingerprint, *pf;
pf = fingerprint = (char *)safe_malloc ((length * 2) + 1);
for (i = 0; i < length; i++)
{
sprintf (pf, "%02X", buff[i]);
pf += 2;
}
*pf = 0;
return fingerprint;
}
/* The actual key ring parser */
static void pgp_make_pgp2_fingerprint (unsigned char *buff,
unsigned char *digest)
{
struct md5_ctx ctx;
unsigned int size = 0;
md5_init_ctx (&ctx);
size = (buff[0] << 8) + buff[1];
size = ((size + 7) / 8);
buff = &buff[2];
md5_process_bytes