1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-07-01 02:42:44 +02:00

* main.h, g10.c (main), revoke.c (gen_desig_revoke): Generate a designated

revocation via --desig-revoke

* keyedit.c (keyedit_menu, menu_addrevoker): New "addrevoker" command to
add a designated revoker to a key.
This commit is contained in:
David Shaw 2002-05-19 15:04:04 +00:00
parent 28ae0d878f
commit 91f05595cc
5 changed files with 414 additions and 7 deletions

View File

@ -1,3 +1,11 @@
2002-05-18 David Shaw <dshaw@jabberwocky.com>
* main.h, g10.c (main), revoke.c (gen_desig_revoke): Generate a
designated revocation via --desig-revoke
* keyedit.c (keyedit_menu, menu_addrevoker): New "addrevoker"
command to add a designated revoker to a key.
2002-05-17 David Shaw <dshaw@jabberwocky.com>
* gpgv.c: Add stub for get_ownertrust().

View File

@ -107,6 +107,7 @@ enum cmd_and_opt_values { aNull = 0,
aExportSecretSub,
aCheckKeys,
aGenRevoke,
aDesigRevoke,
aPrimegen,
aPrintMD,
aPrintMDs,
@ -320,6 +321,7 @@ static ARGPARSE_OPTS opts[] = {
{ aNRLSignKey, "nrlsign-key" ,256, N_("sign a key locally and non-revocably")},
{ aEditKey, "edit-key" ,256, N_("sign or edit a key")},
{ aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")},
{ aDesigRevoke, "desig-revoke",256, "@" },
{ aExport, "export" , 256, N_("export keys") },
{ aSendKeys, "send-keys" , 256, N_("export keys to a key server") },
{ aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") },
@ -975,6 +977,7 @@ main( int argc, char **argv )
case aEditKey: set_cmd( &cmd, aEditKey); greeting=1; break;
case aClearsign: set_cmd( &cmd, aClearsign); break;
case aGenRevoke: set_cmd( &cmd, aGenRevoke); break;
case aDesigRevoke: set_cmd( &cmd, aDesigRevoke); break;
case aVerify: set_cmd( &cmd, aVerify); break;
case aVerifyFiles: set_cmd( &cmd, aVerifyFiles); break;
case aPrimegen: set_cmd( &cmd, aPrimegen); break;
@ -1940,6 +1943,14 @@ main( int argc, char **argv )
m_free( username );
break;
case aDesigRevoke:
if( argc != 1 )
wrong_args("--desig-revoke user-id");
username = make_username(*argv);
gen_desig_revoke( username );
m_free( username );
break;
case aDeArmor:
if( argc > 1 )
wrong_args("--dearmor [file]");

View File

@ -49,6 +49,7 @@ static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock, int photo );
static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_delsig( KBNODE pub_keyblock );
static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock );
@ -877,10 +878,10 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
cmdLSIGN, cmdNRSIGN, cmdNRLSIGN, cmdREVSIG, cmdREVKEY, cmdDELSIG,
cmdPRIMARY, cmdDEBUG, cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID,
cmdADDKEY, cmdDELKEY, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST,
cmdPREF, cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF,
cmdSETPREF, cmdUPDPREF, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST,
cmdCHKTRUST, cmdNOP };
cmdADDKEY, cmdDELKEY, cmdADDREVOKER, cmdTOGGLE, cmdSELKEY,
cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE, cmdENABLEKEY,
cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF, cmdINVCMD,
cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, cmdNOP };
static struct { const char *name;
enum cmdids id;
int need_sk;
@ -913,6 +914,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
{ N_("delphoto"), cmdDELUID , 0,1,0, NULL },
{ N_("addkey") , cmdADDKEY , 1,1,0, N_("add a secondary key") },
{ N_("delkey") , cmdDELKEY , 0,1,0, N_("delete a secondary key") },
{ N_("addrevoker"),cmdADDREVOKER,1,1,0, N_("add a revocation key") },
{ N_("delsig") , cmdDELSIG , 0,1,0, N_("delete signatures") },
{ N_("expire") , cmdEXPIRE , 1,1,0, N_("change the expire date") },
{ N_("primary") , cmdPRIMARY , 1,1,0, N_("flag user ID as primary")},
@ -1247,6 +1249,15 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
}
break;
case cmdADDREVOKER:
if( menu_addrevoker( keyblock, sec_keyblock ) ) {
redisplay = 1;
sec_modified = modified = 1;
merge_keys_and_selfsig( sec_keyblock );
merge_keys_and_selfsig( keyblock );
}
break;
case cmdREVKEY: {
int n1;
@ -2010,6 +2021,139 @@ menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
}
/****************
* Ask for a new revoker, do the selfsignature and put it into
* both keyblocks.
* Return true if there is a new revoker
*/
static int
menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock )
{
PKT_public_key *pk=NULL,*revoker_pk=NULL;
PKT_secret_key *sk=NULL;
PKT_signature *sig=NULL;
PACKET *pkt;
struct revocation_key revkey;
size_t fprlen;
int rc;
assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY);
pk=pub_keyblock->pkt->pkt.public_key;
sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key);
for(;;)
{
char *answer;
u32 keyid[2];
char *p;
size_t n;
if(revoker_pk)
free_public_key(revoker_pk);
revoker_pk=m_alloc_clear(sizeof(*revoker_pk));
tty_printf("\n");
answer=cpr_get_utf8("keyedit.add_revoker",
_("Enter the user ID of the designated revoker: "));
if(answer[0]=='\0' || answer[0]=='\004')
goto fail;
rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL);
if(rc)
{
log_error (_("key `%s' not found: %s\n"),answer,g10_errstr(rc));
continue;
}
fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen);
if(fprlen!=20)
{
log_error(_("cannot appoint a PGP 2.x style key as a "
"designated revoker\n"));
continue;
}
if(cmp_public_keys(revoker_pk,pk)==0)
{
/* This actually causes no harm (after all, a key that
designates itself as a revoker is the same as a
regular key), but it's easy enough to check. */
log_error(_("you cannot appoint a key as its own "
"designated revoker\n"));
continue;
}
keyid_from_pk(revoker_pk,keyid);
tty_printf("\npub %4u%c/%08lX %s ",
nbits_from_pk( revoker_pk ),
pubkey_letter( revoker_pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk(pk) );
p = get_user_id( keyid, &n );
tty_print_utf8_string( p, n );
m_free(p);
tty_printf("\n");
print_fingerprint(revoker_pk,NULL,2);
tty_printf("\n");
tty_printf("WARNING: appointing a key as a designated revoker "
"cannot be undone!\n");
tty_printf("\n");
if(!cpr_get_answer_is_yes("keyedit.add_revoker.okay",
"Are you sure you want to appoint this "
"key as a designated revoker? (y/N): "))
continue;
revkey.class=0x80;
revkey.algid=revoker_pk->pubkey_algo;
free_public_key(revoker_pk);
break;
}
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x1F, 0, 0, 0, 0,
keygen_add_revkey,&revkey );
if( rc )
{
log_error("signing failed: %s\n", g10_errstr(rc) );
goto fail;
}
free_secret_key(sk);
sk=NULL;
/* insert into secret keyblock */
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_SIGNATURE;
pkt->pkt.signature = copy_signature(NULL, sig);
insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
/* insert into public keyblock */
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_SIGNATURE;
pkt->pkt.signature = sig;
insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
return 1;
fail:
if(sk)
free_secret_key(sk);
if(sig)
free_seckey_enc(sig);
if(revoker_pk)
free_public_key(revoker_pk);
return 0;
}
static int
menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )

View File

@ -160,6 +160,7 @@ int enarmor_file( const char *fname );
/*-- revoke.c --*/
struct revocation_reason_info;
int gen_revoke( const char *uname );
int gen_desig_revoke( const char *uname );
int revocation_reason_build_cb( PKT_signature *sig, void *opaque );
struct revocation_reason_info *
ask_revocation_reason( int key_rev, int cert_rev, int hint );

View File

@ -73,6 +73,252 @@ revocation_reason_build_cb( PKT_signature *sig, void *opaque )
/****************
* Generate a revocation certificate for UNAME via a designated revoker
*/
int
gen_desig_revoke( const char *uname )
{
int rc = 0;
armor_filter_context_t afx;
PACKET pkt;
PKT_public_key *pk = NULL;
PKT_secret_key *sk = NULL;
PKT_signature *sig = NULL;
IOBUF out = NULL;
struct revocation_reason_info *reason = NULL;
KEYDB_HANDLE kdbhd;
KEYDB_SEARCH_DESC desc;
KBNODE keyblock=NULL,node;
u32 keyid[2];
int i,any=0;
if( opt.batch ) {
log_error(_("sorry, can't do this in batch mode\n"));
return G10ERR_GENERAL;
}
memset( &afx, 0, sizeof afx);
kdbhd = keydb_new (0);
classify_user_id (uname, &desc);
rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID;
if (rc) {
log_error (_("key `%s' not found: %s\n"),uname, g10_errstr (rc));
goto leave;
}
rc = keydb_get_keyblock (kdbhd, &keyblock );
if( rc ) {
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
goto leave;
}
/* To parse the revkeys */
merge_keys_and_selfsig(keyblock);
/* get the key from the keyblock */
node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
if( !node )
BUG ();
pk=node->pkt->pkt.public_key;
keyid_from_pk(pk,keyid);
/* Are we a designated revoker for this key? */
if(!pk->revkey && pk->numrevkeys)
BUG();
for(i=0;i<pk->numrevkeys;i++)
{
if(sk)
free_secret_key(sk);
sk=m_alloc_clear(sizeof(*sk));
rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN);
/* We have the revocation key */
if(!rc)
{
size_t n;
char *p;
u32 sk_keyid[2];
PKT_user_id *uid=NULL;
PKT_signature *selfsig=NULL;
any=1;
keyid_from_sk(sk,sk_keyid);
tty_printf("\npub %4u%c/%08lX %s ",
nbits_from_pk( pk ),
pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk(pk) );
p = get_user_id( keyid, &n );
tty_print_utf8_string( p, n );
m_free(p);
tty_printf("\n\n");
tty_printf(_("To be revoked by:\n"));
tty_printf("\nsec %4u%c/%08lX %s ",
nbits_from_sk( sk ),
pubkey_letter( sk->pubkey_algo ),
(ulong)sk_keyid[1], datestr_from_sk(sk) );
p = get_user_id( sk_keyid, &n );
tty_print_utf8_string( p, n );
m_free(p);
tty_printf("\n\n");
if( !cpr_get_answer_is_yes("gen_desig_revoke.okay",
_("Create a revocation certificate for this key? ")) )
continue;
/* get the reason for the revocation (this is always v4) */
reason = ask_revocation_reason( 1, 0, 1 );
if( !reason )
continue;
rc = check_secret_key( sk, 0 );
if( rc )
continue;
if( !opt.armor )
tty_printf(_("ASCII armored output forced.\n"));
if( (rc = open_outfile( NULL, 0, &out )) )
goto leave;
afx.what = 1;
afx.hdrlines = "Comment: A revocation certificate should follow\n";
iobuf_push_filter( out, armor_filter, &afx );
/* create it */
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
0, 0, 0,
revocation_reason_build_cb, reason );
if( rc ) {
log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
goto leave;
}
/* Spit out a minimal pk as well, since otherwise there is
no way to know which key to attach this revocation
to. */
node=find_kbnode(keyblock,PKT_PUBLIC_KEY);
if(!node)
{
rc=G10ERR_GENERAL;
log_error(_("key %08lX incomplete\n"),(ulong)keyid[1]);
goto leave;
}
pkt = *node->pkt;
rc=build_packet(out,&pkt);
if( rc ) {
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
goto leave;
}
init_packet( &pkt );
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
rc = build_packet( out, &pkt );
if( rc ) {
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
goto leave;
}
while(!selfsig)
{
KBNODE signode;
node=find_next_kbnode(node,PKT_USER_ID);
if(!node)
{
/* We're out of user IDs - none were
self-signed. */
if(uid)
break;
else
{
rc=G10ERR_GENERAL;
log_error(_("key %08lX incomplete\n"),(ulong)keyid[1]);
goto leave;
}
}
if(node->pkt->pkt.user_id->attrib_data)
continue;
uid=node->pkt->pkt.user_id;
signode=node;
while((signode=find_next_kbnode(signode,PKT_SIGNATURE)))
{
if(keyid[0]==signode->pkt->pkt.signature->keyid[0] &&
keyid[1]==signode->pkt->pkt.signature->keyid[1] &&
IS_UID_SIG(signode->pkt->pkt.signature))
{
selfsig=signode->pkt->pkt.signature;
break;
}
}
}
pkt.pkttype = PKT_USER_ID;
pkt.pkt.user_id = uid;
rc = build_packet( out, &pkt );
if( rc ) {
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
goto leave;
}
if(selfsig)
{
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = selfsig;
rc = build_packet( out, &pkt );
if( rc ) {
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
goto leave;
}
}
/* and issue a usage notice */
tty_printf(_("Revocation certificate created.\n"));
break;
}
}
if(!any)
log_error(_("no revocation keys found for `%s'\n"),uname);
leave:
if( pk )
free_public_key( pk );
if( sk )
free_secret_key( sk );
if( sig )
free_seckey_enc( sig );
if( rc )
iobuf_cancel(out);
else
iobuf_close(out);
release_revocation_reason_info( reason );
return rc;
}
/****************
* Generate a revocation certificate for UNAME
*/
@ -81,7 +327,6 @@ gen_revoke( const char *uname )
{
int rc = 0;
armor_filter_context_t afx;
compress_filter_context_t zfx;
PACKET pkt;
PKT_secret_key *sk; /* used as pointer into a kbnode */
PKT_public_key *pk = NULL;
@ -100,7 +345,6 @@ gen_revoke( const char *uname )
}
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
init_packet( &pkt );
/* search the userid:
@ -363,4 +607,3 @@ release_revocation_reason_info( struct revocation_reason_info *reason )
m_free( reason );
}
}