mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Auto-create revocation certificates.
* configure.ac (GNUPG_OPENPGP_REVOC_DIR): New config define. * g10/revoke.c (create_revocation): Add arg "leadin". (gen_standard_revoke): New. * g10/openfile.c (get_openpgp_revocdir): New. (open_outfile): Add MODE value 3. * g10/keyid.c (hexfingerprint): New. * g10/keygen.c (do_generate_keypair): Call gen_standard_revoke. -- GnuPG-bug-id: 1042
This commit is contained in:
parent
aa5b4392aa
commit
03018ef9ee
@ -444,7 +444,8 @@ AH_BOTTOM([
|
|||||||
#else
|
#else
|
||||||
#define GNUPG_DEFAULT_HOMEDIR "~/.gnupg"
|
#define GNUPG_DEFAULT_HOMEDIR "~/.gnupg"
|
||||||
#endif
|
#endif
|
||||||
#define GNUPG_PRIVATE_KEYS_DIR "private-keys-v1.d"
|
#define GNUPG_PRIVATE_KEYS_DIR "private-keys-v1.d"
|
||||||
|
#define GNUPG_OPENPGP_REVOC_DIR "openpgp-revocs.d"
|
||||||
|
|
||||||
/* For some systems (DOS currently), we hardcode the path here. For
|
/* For some systems (DOS currently), we hardcode the path here. For
|
||||||
POSIX systems the values are constructed by the Makefiles, so that
|
POSIX systems the values are constructed by the Makefiles, so that
|
||||||
|
@ -3106,6 +3106,15 @@ files; They all live in in the current home directory (@pxref{option
|
|||||||
@item ~/.gnupg/secring.gpg.lock
|
@item ~/.gnupg/secring.gpg.lock
|
||||||
The lock file for the secret keyring.
|
The lock file for the secret keyring.
|
||||||
|
|
||||||
|
@item ~/.gnupg/openpgp-revocs.d/
|
||||||
|
This is the directory where gpg stores pre-generated revocation
|
||||||
|
certificates. It is suggested to backup those certificates and if the
|
||||||
|
primary private key is not stored on the disk to move them to an
|
||||||
|
external storage device. Anyone who can access theses files is able to
|
||||||
|
revoke the corresponding key. You may want to print them out. You
|
||||||
|
should backup all files in this directory and take care to keep this
|
||||||
|
backup closed away.
|
||||||
|
|
||||||
@item /usr[/local]/share/gnupg/options.skel
|
@item /usr[/local]/share/gnupg/options.skel
|
||||||
The skeleton options file.
|
The skeleton options file.
|
||||||
|
|
||||||
|
@ -288,6 +288,7 @@ const char *colon_datestr_from_pk (PKT_public_key *pk);
|
|||||||
const char *colon_datestr_from_sig (PKT_signature *sig);
|
const char *colon_datestr_from_sig (PKT_signature *sig);
|
||||||
const char *colon_expirestr_from_sig (PKT_signature *sig);
|
const char *colon_expirestr_from_sig (PKT_signature *sig);
|
||||||
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
|
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
|
||||||
|
char *hexfingerprint (PKT_public_key *pk);
|
||||||
gpg_error_t keygrip_from_pk (PKT_public_key *pk, unsigned char *array);
|
gpg_error_t keygrip_from_pk (PKT_public_key *pk, unsigned char *array);
|
||||||
gpg_error_t hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip);
|
gpg_error_t hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip);
|
||||||
|
|
||||||
|
@ -4000,6 +4000,8 @@ do_generate_keypair (struct para_data_s *para,
|
|||||||
update_ownertrust (pk, ((get_ownertrust (pk) & ~TRUST_MASK)
|
update_ownertrust (pk, ((get_ownertrust (pk) & ~TRUST_MASK)
|
||||||
| TRUST_ULTIMATE ));
|
| TRUST_ULTIMATE ));
|
||||||
|
|
||||||
|
gen_standard_revoke (pk);
|
||||||
|
|
||||||
if (!opt.batch)
|
if (!opt.batch)
|
||||||
{
|
{
|
||||||
tty_printf (_("public and secret key created and signed.\n") );
|
tty_printf (_("public and secret key created and signed.\n") );
|
||||||
|
14
g10/keyid.c
14
g10/keyid.c
@ -772,6 +772,20 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return an allocated buffer with the fingerprint of PK formatted as
|
||||||
|
a plain hexstring. */
|
||||||
|
char *
|
||||||
|
hexfingerprint (PKT_public_key *pk)
|
||||||
|
{
|
||||||
|
unsigned char fpr[MAX_FINGERPRINT_LEN];
|
||||||
|
size_t len;
|
||||||
|
char *result;
|
||||||
|
|
||||||
|
fingerprint_from_pk (pk, fpr, &len);
|
||||||
|
result = xmalloc (2 * len + 1);
|
||||||
|
bin2hex (fpr, len, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -274,6 +274,7 @@ int open_outfile (int inp_fd, const char *iname, int mode,
|
|||||||
int restrictedperm, iobuf_t *a);
|
int restrictedperm, iobuf_t *a);
|
||||||
iobuf_t open_sigfile( const char *iname, progress_filter_context_t *pfx );
|
iobuf_t open_sigfile( const char *iname, progress_filter_context_t *pfx );
|
||||||
void try_make_homedir( const char *fname );
|
void try_make_homedir( const char *fname );
|
||||||
|
char *get_openpgp_revocdir (const char *home);
|
||||||
|
|
||||||
/*-- seskey.c --*/
|
/*-- seskey.c --*/
|
||||||
void make_session_key( DEK *dek );
|
void make_session_key( DEK *dek );
|
||||||
@ -317,6 +318,7 @@ int enarmor_file( const char *fname );
|
|||||||
|
|
||||||
/*-- revoke.c --*/
|
/*-- revoke.c --*/
|
||||||
struct revocation_reason_info;
|
struct revocation_reason_info;
|
||||||
|
int gen_standard_revoke (PKT_public_key *psk);
|
||||||
int gen_revoke( const char *uname );
|
int gen_revoke( const char *uname );
|
||||||
int gen_desig_revoke( const char *uname, strlist_t locusr);
|
int gen_desig_revoke( const char *uname, strlist_t locusr);
|
||||||
int revocation_reason_build_cb( PKT_signature *sig, void *opaque );
|
int revocation_reason_build_cb( PKT_signature *sig, void *opaque );
|
||||||
|
@ -174,9 +174,10 @@ ask_outfile_name( const char *name, size_t namelen )
|
|||||||
* Mode 0 = use ".gpg"
|
* Mode 0 = use ".gpg"
|
||||||
* 1 = use ".asc"
|
* 1 = use ".asc"
|
||||||
* 2 = use ".sig"
|
* 2 = use ".sig"
|
||||||
|
* 3 = use ".rev"
|
||||||
*
|
*
|
||||||
* If INP_FD is not -1 the function simply creates an IOBUF for that
|
* If INP_FD is not -1 the function simply creates an IOBUF for that
|
||||||
* file descriptor and ignorea INAME and MODE. Note that INP_FD won't
|
* file descriptor and ignore INAME and MODE. Note that INP_FD won't
|
||||||
* be closed if the returned IOBUF is closed. With RESTRICTEDPERM a
|
* be closed if the returned IOBUF is closed. With RESTRICTEDPERM a
|
||||||
* file will be created with mode 700 if possible.
|
* file will be created with mode 700 if possible.
|
||||||
*/
|
*/
|
||||||
@ -239,7 +240,8 @@ open_outfile (int inp_fd, const char *iname, int mode, int restrictedperm,
|
|||||||
const char *newsfx;
|
const char *newsfx;
|
||||||
|
|
||||||
newsfx = (mode==1 ? ".asc" :
|
newsfx = (mode==1 ? ".asc" :
|
||||||
mode==2 ? ".sig" : ".gpg");
|
mode==2 ? ".sig" :
|
||||||
|
mode==3 ? ".rev" : ".gpg");
|
||||||
|
|
||||||
buf = xmalloc (strlen(iname)+4+1);
|
buf = xmalloc (strlen(iname)+4+1);
|
||||||
strcpy (buf, iname);
|
strcpy (buf, iname);
|
||||||
@ -258,6 +260,7 @@ open_outfile (int inp_fd, const char *iname, int mode, int restrictedperm,
|
|||||||
buf = xstrconcat (iname,
|
buf = xstrconcat (iname,
|
||||||
(mode==1 ? EXTSEP_S "asc" :
|
(mode==1 ? EXTSEP_S "asc" :
|
||||||
mode==2 ? EXTSEP_S "sig" :
|
mode==2 ? EXTSEP_S "sig" :
|
||||||
|
mode==3 ? EXTSEP_S "rev" :
|
||||||
/* */ EXTSEP_S GPGEXT_GPG),
|
/* */ EXTSEP_S GPGEXT_GPG),
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
@ -451,3 +454,24 @@ try_make_homedir (const char *fname)
|
|||||||
copy_options_file( fname );
|
copy_options_file( fname );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get and if needed create a string with the directory used to store
|
||||||
|
openpgp revocations. */
|
||||||
|
char *
|
||||||
|
get_openpgp_revocdir (const char *home)
|
||||||
|
{
|
||||||
|
char *fname;
|
||||||
|
struct stat statbuf;
|
||||||
|
|
||||||
|
fname = make_filename (home, GNUPG_OPENPGP_REVOC_DIR, NULL);
|
||||||
|
if (stat (fname, &statbuf) && errno == ENOENT)
|
||||||
|
{
|
||||||
|
if (gnupg_mkdir (fname, "-rwx"))
|
||||||
|
log_error (_("can't create directory '%s': %s\n"),
|
||||||
|
fname, strerror (errno) );
|
||||||
|
else if (!opt.quiet)
|
||||||
|
log_info (_("directory '%s' created\n"), fname);
|
||||||
|
}
|
||||||
|
return fname;
|
||||||
|
}
|
||||||
|
@ -633,7 +633,8 @@ emit_status_need_passphrase (u32 *keyid, u32 *mainkeyid, int pubkey_algo)
|
|||||||
|
|
||||||
/* Return an allocated utf-8 string describing the key PK. If ESCAPED
|
/* Return an allocated utf-8 string describing the key PK. If ESCAPED
|
||||||
is true spaces and control characters are percent or plus escaped.
|
is true spaces and control characters are percent or plus escaped.
|
||||||
MODE 0 is for the common prompt, MODE 1 for the import prompt. */
|
MODE describes the use of the key description; use one of the
|
||||||
|
FORMAT_KEYDESC_ macros. */
|
||||||
char *
|
char *
|
||||||
gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped)
|
gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped)
|
||||||
{
|
{
|
||||||
|
88
g10/revoke.c
88
g10/revoke.c
@ -436,12 +436,14 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
|
|||||||
revocation reason. PSK is the public primary key - we expect that
|
revocation reason. PSK is the public primary key - we expect that
|
||||||
a corresponding secret key is available. KEYBLOCK is the entire
|
a corresponding secret key is available. KEYBLOCK is the entire
|
||||||
KEYBLOCK which is used in PGP mode to write a a minimal key and not
|
KEYBLOCK which is used in PGP mode to write a a minimal key and not
|
||||||
just the naked revocation signature; it may be NULL. */
|
just the naked revocation signature; it may be NULL. If LEADINTEXT
|
||||||
|
is not NULL, it is written right before the (armored) output.*/
|
||||||
static int
|
static int
|
||||||
create_revocation (const char *filename,
|
create_revocation (const char *filename,
|
||||||
struct revocation_reason_info *reason,
|
struct revocation_reason_info *reason,
|
||||||
PKT_public_key *psk,
|
PKT_public_key *psk,
|
||||||
kbnode_t keyblock)
|
kbnode_t keyblock,
|
||||||
|
const char *leadintext, int suffix)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
iobuf_t out = NULL;
|
iobuf_t out = NULL;
|
||||||
@ -451,9 +453,12 @@ create_revocation (const char *filename,
|
|||||||
|
|
||||||
afx = new_armor_context ();
|
afx = new_armor_context ();
|
||||||
|
|
||||||
if ((rc = open_outfile (-1, filename, 0, 1, &out)))
|
if ((rc = open_outfile (-1, filename, suffix, 1, &out)))
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
if (leadintext )
|
||||||
|
iobuf_writestr (out, leadintext);
|
||||||
|
|
||||||
afx->what = 1;
|
afx->what = 1;
|
||||||
afx->hdrlines = "Comment: This is a revocation certificate\n";
|
afx->hdrlines = "Comment: This is a revocation certificate\n";
|
||||||
push_armor_filter (afx, out);
|
push_armor_filter (afx, out);
|
||||||
@ -502,6 +507,81 @@ create_revocation (const char *filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function is used to generate a standard revocation certificate
|
||||||
|
by gpg's interactive key generation function. The certificate is
|
||||||
|
stored at a dedicated place in a slightly modified form to avoid an
|
||||||
|
accidental import. PSK is the primary key; a corresponding secret
|
||||||
|
key must be available. */
|
||||||
|
int
|
||||||
|
gen_standard_revoke (PKT_public_key *psk)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
estream_t memfp;
|
||||||
|
struct revocation_reason_info reason;
|
||||||
|
char *dir, *tmpstr, *fname;
|
||||||
|
void *leadin;
|
||||||
|
size_t len;
|
||||||
|
u32 keyid[2];
|
||||||
|
char pkstrbuf[PUBKEY_STRING_SIZE];
|
||||||
|
char *orig_codeset;
|
||||||
|
|
||||||
|
dir = get_openpgp_revocdir (opt.homedir);
|
||||||
|
tmpstr = hexfingerprint (psk);
|
||||||
|
fname = xstrconcat (dir, DIRSEP_S, tmpstr, NULL);
|
||||||
|
xfree (tmpstr);
|
||||||
|
xfree (dir);
|
||||||
|
|
||||||
|
keyid_from_pk (psk, keyid);
|
||||||
|
|
||||||
|
memfp = es_fopenmem (0, "r+");
|
||||||
|
if (!memfp)
|
||||||
|
log_fatal ("error creating memory stream\n");
|
||||||
|
|
||||||
|
orig_codeset = i18n_switchto_utf8 ();
|
||||||
|
|
||||||
|
es_fprintf (memfp, "%s\n\n",
|
||||||
|
_("This is a revocation certificate for the OpenPGP key:"));
|
||||||
|
|
||||||
|
es_fprintf (memfp, "pub %s/%s %s\n",
|
||||||
|
pubkey_string (psk, pkstrbuf, sizeof pkstrbuf),
|
||||||
|
keystr (keyid),
|
||||||
|
datestr_from_pk (psk));
|
||||||
|
|
||||||
|
print_fingerprint (memfp, psk, 3);
|
||||||
|
|
||||||
|
tmpstr = get_user_id (keyid, &len);
|
||||||
|
es_fprintf (memfp, "uid%*s%.*s\n\n",
|
||||||
|
(int)keystrlen () + 10, "",
|
||||||
|
(int)len, tmpstr);
|
||||||
|
xfree (tmpstr);
|
||||||
|
|
||||||
|
es_fprintf (memfp, "%s\n\n%s\n\n:",
|
||||||
|
_("Use it to revoke this key in case of a compromise or loss of\n"
|
||||||
|
"the secret key. However, if the secret key is still accessible,\n"
|
||||||
|
"it is better to generate a new revocation certificate and give\n"
|
||||||
|
"a reason for the revocation."),
|
||||||
|
_("To avoid an accidental use of this file, a colon has been inserted\n"
|
||||||
|
"before the 5 dashes below. Remove this colon with a text editor\n"
|
||||||
|
"before making use of this revocation certificate."));
|
||||||
|
|
||||||
|
es_putc (0, memfp);
|
||||||
|
|
||||||
|
i18n_switchback (orig_codeset);
|
||||||
|
|
||||||
|
if (es_fclose_snatch (memfp, &leadin, NULL))
|
||||||
|
log_fatal ("error snatching memory stream\n");
|
||||||
|
|
||||||
|
reason.code = 0x00; /* No particular reason. */
|
||||||
|
reason.desc = NULL;
|
||||||
|
rc = create_revocation (fname, &reason, psk, NULL, leadin, 3);
|
||||||
|
xfree (leadin);
|
||||||
|
xfree (fname);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
* Generate a revocation certificate for UNAME
|
* Generate a revocation certificate for UNAME
|
||||||
*/
|
*/
|
||||||
@ -582,7 +662,7 @@ gen_revoke (const char *uname)
|
|||||||
if (!opt.armor)
|
if (!opt.armor)
|
||||||
tty_printf (_("ASCII armored output forced.\n"));
|
tty_printf (_("ASCII armored output forced.\n"));
|
||||||
|
|
||||||
rc = create_revocation (NULL, reason, psk, keyblock);
|
rc = create_revocation (NULL, reason, psk, keyblock, NULL, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ CLEANFILES = prepared.stamp x y yy z out err $(data_files) \
|
|||||||
gnupg-test.stop pubring.gpg~ random_seed gpg-agent.log
|
gnupg-test.stop pubring.gpg~ random_seed gpg-agent.log
|
||||||
|
|
||||||
clean-local:
|
clean-local:
|
||||||
-rm -rf private-keys-v1.d
|
-rm -rf private-keys-v1.d openpgp-revocs.d
|
||||||
|
|
||||||
|
|
||||||
# We need to depend on a couple of programs so that the tests don't
|
# We need to depend on a couple of programs so that the tests don't
|
||||||
|
Loading…
x
Reference in New Issue
Block a user