diff --git a/NEWS b/NEWS index dc45c6ef3..774589a1a 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,7 @@ * New option -N to insert notations and a --set-policy-url. - + * New subcommand "delsig" in th edit menu. Noteworthy changes in version 0.9.7 diff --git a/TODO b/TODO index 32143b409..df6a958a6 100644 --- a/TODO +++ b/TODO @@ -1,10 +1,4 @@ - * gppm links in doc und bin sind inkonsistent - - * remove signature: -Got an idea: just specify the keyid of the signature - this can be -done quite easily. - * add some status output put for signing and encryption. replace the putc in primegen with some kind of status-fd outputs. diff --git a/doc/Makefile.am b/doc/Makefile.am index 8be224b0c..460a63dbb 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -6,13 +6,6 @@ man_MANS = gpg.1 -install-data-hook: - if test -f $(man1dir)/gpgm.1; then rm $(man1dir)/gpgm.1; fi - ln -s $(man1dir)/gpg.1 $(man1dir)/gpgm.1 \ - || ln $(man1dir)/gpg.1 $(man1dir)/gpgm.1 - - - %: %pod pod2man $< --section=`echo $@ | sed 's/^.*(?)$$/$$&/'`\ --release="`date -r $< '+%d %b %Y'`"\ diff --git a/g10/ChangeLog b/g10/ChangeLog index fafbe61e3..6c1fe9f50 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,10 @@ +Thu May 27 09:40:55 CEST 1999 Werner Koch + + * status.c (cpr_get_answer_yes_no_quit): New. + * keyedit.c (menu_delsig): New. + (check_all_keysigs): Splitted. + (print_and_check_one_sig): New. + Wed May 26 14:36:29 CEST 1999 Werner Koch * build-packet.c (build_sig_subpkt): Support large packets. diff --git a/g10/Makefile.am b/g10/Makefile.am index c32dc4413..bb939c933 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -85,8 +85,8 @@ install-data-local: $(mkinstalldirs) $(pkgdatadir) $(INSTALL_DATA) $(srcdir)/options.skel $(pkgdatadir)/options.skel @set -e;\ - if test -f $(bindir)/gpgm ; then \ - rm $(bindir)/gpgm ; ln -s gpg $(bindir)/gpgm ; \ + if test -f $(bindir)/gpgm ; then + echo "removing obsolete gpgm binary" + rm $(bindir)/gpgm ; fi - diff --git a/g10/helptext.c b/g10/helptext.c index 459f62ed7..7643f96db 100644 --- a/g10/helptext.c +++ b/g10/helptext.c @@ -172,6 +172,26 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = { "Answer \"yes\" if it is okay to delete the subkey" }, + +{ N_("keyedit.delsig.valid"), + "This is a valid signature on the key; you normally don't want\n" + "to delete this signature may be important to establish a trust\n" + "connection to the key or another key certified by this key." +}, +{ N_("keyedit.delsig.invalid"), + "The signature is not valid. It does make sense to remove it from\n" + "your keyring if it is really invalid and not just unchecked due to\n" + "a missing public key (marked by \"sig?\")." +}, +{ N_("keyedit.delsig.selfsig"), + "This is a signature which binds the user ID to the key. It is\n" + "usually not a good idea to remove such a signature. Actually\n" + "GnuPG might not be able to use this key anymore. So do this\n" + "only if this self-signature is for some reason not valid and\n" + "a second one is available." +}, + + { N_("passphrase.enter"), "" "Please enter the passhrase; this is a secret sentence \n" diff --git a/g10/keyedit.c b/g10/keyedit.c index 55bd73a08..5777e7181 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -47,6 +47,7 @@ static void show_key_and_fingerprint( KBNODE keyblock ); static void show_fingerprint( PKT_public_key *pk ); static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock ); 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_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_select_uid( KBNODE keyblock, int idx ); @@ -103,6 +104,68 @@ get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username ) } +/**************** + * Print information about a signature, chek it and return true + * if the signature is okay. NODE must be a signature packet. + */ +static int +print_and_check_one_sig( KBNODE keyblock, KBNODE node, + int *inv_sigs, int *no_key, int *oth_err, + int *is_selfsig ) +{ + PKT_signature *sig = node->pkt->pkt.signature; + int rc, sigrc; + int is_rev = sig->sig_class == 0x30; + + switch( (rc = check_key_signature( keyblock, node, is_selfsig)) ) { + case 0: + node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR); + sigrc = '!'; + break; + case G10ERR_BAD_SIGN: + node->flag = NODFLG_BADSIG; + sigrc = '-'; + if( inv_sigs ) + ++*inv_sigs; + break; + case G10ERR_NO_PUBKEY: + node->flag = NODFLG_NOKEY; + sigrc = '?'; + if( no_key ) + ++*no_key; + break; + default: + node->flag = NODFLG_SIGERR; + sigrc = '%'; + if( oth_err ) + ++*oth_err; + break; + } + if( sigrc != '?' ) { + tty_printf("%s%c %08lX %s ", + is_rev? "rev":"sig", + sigrc, sig->keyid[1], datestr_from_sig(sig)); + if( sigrc == '%' ) + tty_printf("[%s] ", g10_errstr(rc) ); + else if( sigrc == '?' ) + ; + else if( *is_selfsig ) { + tty_printf( is_rev? _("[revocation]") + : _("[self-signature]") ); + } + else { + size_t n; + char *p = get_user_id( sig->keyid, &n ); + tty_print_string( p, n > 40? 40 : n ); + m_free(p); + } + tty_printf("\n"); + } + return (sigrc == '!'); +} + + + /**************** * Check the keysigs and set the flags to indicate errors. * Returns true if error found. @@ -112,7 +175,6 @@ check_all_keysigs( KBNODE keyblock, int only_selected ) { KBNODE kbctx; KBNODE node; - int rc; int inv_sigs = 0; int no_key = 0; int oth_err = 0; @@ -140,54 +202,14 @@ check_all_keysigs( KBNODE keyblock, int only_selected ) else if( selected && node->pkt->pkttype == PKT_SIGNATURE && ( (node->pkt->pkt.signature->sig_class&~3) == 0x10 || node->pkt->pkt.signature->sig_class == 0x30 ) ) { - PKT_signature *sig = node->pkt->pkt.signature; - int sigrc, selfsig; - int is_rev = sig->sig_class == 0x30; + int selfsig; - switch( (rc = check_key_signature( keyblock, node, &selfsig)) ) { - case 0: - node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR); - sigrc = '!'; - break; - case G10ERR_BAD_SIGN: - node->flag = NODFLG_BADSIG; - sigrc = '-'; - inv_sigs++; - break; - case G10ERR_NO_PUBKEY: - node->flag = NODFLG_NOKEY; - sigrc = '?'; - no_key++; - break; - default: - node->flag = NODFLG_SIGERR; - sigrc = '%'; - oth_err++; - break; - } - if( sigrc != '?' ) { - tty_printf("%s%c %08lX %s ", - is_rev? "rev":"sig", - sigrc, sig->keyid[1], datestr_from_sig(sig)); - if( sigrc == '%' ) - tty_printf("[%s] ", g10_errstr(rc) ); - else if( sigrc == '?' ) - ; - else if( selfsig ) { - tty_printf( is_rev? _("[revocation]") - : _("[self-signature]") ); - if( sigrc == '!' ) - has_selfsig = 1; - } - else { - size_t n; - char *p = get_user_id( sig->keyid, &n ); - tty_print_string( p, n > 40? 40 : n ); - m_free(p); - } - tty_printf("\n"); - /* fixme: Should we update the trustdb here */ + if( print_and_check_one_sig( keyblock, node, &inv_sigs, + &no_key, &oth_err, &selfsig ) ) { + if( selfsig ) + has_selfsig = 1; } + /* Hmmm: should we update the trustdb here? */ } } if( !has_selfsig ) @@ -525,7 +547,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands ) { enum cmdids { cmdNONE = 0, cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN, - cmdLSIGN, cmdREVSIG, cmdREVKEY, + cmdLSIGN, cmdREVSIG, cmdREVKEY, cmdDELSIG, cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE, cmdNOP }; @@ -554,6 +576,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands ) { N_("deluid") , cmdDELUID , 0, N_("delete user id") }, { N_("addkey") , cmdADDKEY , 1, N_("add a secondary key") }, { N_("delkey") , cmdDELKEY , 0, N_("delete a secondary key") }, + { N_("delsig") , cmdDELSIG , 0, N_("delete signatures") }, { N_("expire") , cmdEXPIRE , 1, N_("change the expire date") }, { N_("toggle") , cmdTOGGLE , 1, N_("toggle between secret " "and public key listing") }, @@ -805,6 +828,19 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands ) } break; + case cmdDELSIG: { + int n1; + + if( !(n1=count_selected_uids(keyblock)) ) + tty_printf(_("You must select at least one user id.\n")); + else if( menu_delsig( keyblock ) ) { + /* no redisplay here, because it may scroll away some + * status output of delsig */ + modified = 1; + } + } + break; + case cmdADDKEY: if( generate_subkeypair( keyblock, sec_keyblock ) ) { redisplay = 1; @@ -1227,6 +1263,61 @@ menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock ) } +static int +menu_delsig( KBNODE pub_keyblock ) +{ + KBNODE node; + PKT_user_id *uid = NULL; + int changed=0; + + for( node = pub_keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_USER_ID ) { + uid = (node->flag & NODFLG_SELUID)? node->pkt->pkt.user_id : NULL; + } + else if( uid && node->pkt->pkttype == PKT_SIGNATURE ) { + int okay, valid, selfsig; + + tty_printf("uid "); + tty_print_string( uid->name, uid->len ); + tty_printf("\n"); + + valid = print_and_check_one_sig( pub_keyblock, node, + NULL, NULL, NULL, &selfsig ); + + okay = valid ? cpr_get_answer_yes_no_quit( + "keyedit.delsig.valid", + _("Delete this good signature? (y/N/q)")) + : cpr_get_answer_yes_no_quit( + "keyedit.delsig.invalid", + _("Delete this invalid signature? (y/N/q)")); + if( okay == -1 ) + break; + if( okay && !cpr_get_answer_is_yes( + "keyedit.delsig.selfsig", + _("Really delete this self-signature? (y/N)") )) + okay = 0; + if( okay ) { + delete_kbnode( node ); + changed++; + } + + } + else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + uid = NULL; + } + + if( changed ) { + commit_kbnode( &pub_keyblock ); + tty_printf( changed == 1? _("Deleted %d signature.\n") + : _("Deleted %d signatures.\n"), changed ); + } + else + tty_printf( _("Nothing deleted.\n") ); + + return changed; +} + + /**************** * Remove some of the secondary keys */ diff --git a/g10/status.c b/g10/status.c index a832ea713..d068a4537 100644 --- a/g10/status.c +++ b/g10/status.c @@ -358,3 +358,29 @@ cpr_get_answer_is_yes( const char *keyword, const char *prompt ) } } +int +cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ) +{ + int yes; + char *p; + + #ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return !!do_shm_get( keyword, 0, 1 ); + #endif + for(;;) { + p = tty_get( prompt ); + trim_spaces(p); /* it is okay to do this here */ + if( *p == '?' && !p[1] ) { + m_free(p); + display_online_help( keyword ); + } + else { + tty_kill_prompt(); + yes = answer_is_yes_no_quit(p); + m_free(p); + return yes; + } + } +} + diff --git a/g10/status.h b/g10/status.h index d8e13b70e..2cb72fec3 100644 --- a/g10/status.h +++ b/g10/status.h @@ -80,6 +80,7 @@ char *cpr_get_utf8( const char *keyword, const char *prompt ); char *cpr_get_hidden( const char *keyword, const char *prompt ); void cpr_kill_prompt(void); int cpr_get_answer_is_yes( const char *keyword, const char *prompt ); +int cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ); #endif /*G10_STATUS_H*/ diff --git a/include/util.h b/include/util.h index f62f34de8..9a4f1ffb5 100644 --- a/include/util.h +++ b/include/util.h @@ -154,6 +154,7 @@ const char *strtimestamp( u32 stamp ); /* GMT */ const char *asctimestamp( u32 stamp ); /* localized */ void print_string( FILE *fp, const byte *p, size_t n, int delim ); int answer_is_yes( const char *s ); +int answer_is_yes_no_quit( const char *s ); /*-- strgutil.c --*/ void free_strlist( STRLIST sl ); diff --git a/util/ChangeLog b/util/ChangeLog index 0ec6deb40..bf0ebb5f9 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,7 @@ +Thu May 27 09:40:55 CEST 1999 Werner Koch + + * miscutil.c (answer_is_yes_no_quit): New. + Sun May 23 14:20:22 CEST 1999 Werner Koch * dotlock.c: Tweaked to make it compile under mingw32 diff --git a/util/miscutil.c b/util/miscutil.c index d902ae435..d982e64af 100644 --- a/util/miscutil.c +++ b/util/miscutil.c @@ -164,3 +164,26 @@ answer_is_yes( const char *s ) } +/**************** + * Return 1 for yes, -1 for quit, or 0 for no + */ +int +answer_is_yes_no_quit( const char *s ) +{ + char *long_yes = _("yes"); + char *long_quit = _("quit"); + char *short_yes = _("yY"); + char *short_quit = _("qQ"); + + if( !stricmp(s, long_yes ) ) + return 1; + if( !stricmp(s, long_quit ) ) + return -1; + if( strchr( short_yes, *s ) && !s[1] ) + return 1; + if( strchr( short_quit, *s ) && !s[1] ) + return -1; + return 0; +} + +