aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shaw <[email protected]>2002-05-19 15:04:04 +0000
committerDavid Shaw <[email protected]>2002-05-19 15:04:04 +0000
commit91f05595cc286fd4b20240bc6189a463eb8075e3 (patch)
tree6b31f277c8d7e3ef266780cacc0ce796164e5dd6
parent* gpgv.c: Add stub for get_ownertrust(). (diff)
downloadgnupg-91f05595cc286fd4b20240bc6189a463eb8075e3.tar.gz
gnupg-91f05595cc286fd4b20240bc6189a463eb8075e3.zip
* 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.
-rw-r--r--g10/ChangeLog8
-rw-r--r--g10/g10.c11
-rw-r--r--g10/keyedit.c152
-rw-r--r--g10/main.h1
-rw-r--r--g10/revoke.c249
5 files changed, 414 insertions, 7 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index d42eabfc0..901d92eb9 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,11 @@
+2002-05-18 David Shaw <[email protected]>
+
+ * 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 <[email protected]>
* gpgv.c: Add stub for get_ownertrust().
diff --git a/g10/g10.c b/g10/g10.c
index 0270e83ae..48c0c76a7 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -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]");
diff --git a/g10/keyedit.c b/g10/keyedit.c
index b27b64706..6c54c6a7b 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -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 )
diff --git a/g10/main.h b/g10/main.h
index 6400a5f99..b91bedcac 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -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 );
diff --git a/g10/revoke.c b/g10/revoke.c
index 3ea8c035b..ca67d80e5 100644
--- a/g10/revoke.c
+++ b/g10/revoke.c
@@ -74,6 +74,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
*/
int
@@ -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 );
}
}
-