From f0bf8b4afcb78cdb2ab89b8f71de00e0d689064a Mon Sep 17 00:00:00 2001 From: David Shaw Date: Mon, 3 Jun 2002 20:48:36 +0000 Subject: [PATCH] * main.h, g10.c (main), keylist.c (dump_attribs, set_attrib_fd, list_keyblock_print, list_keyblock_colon), status.h, status.c (get_status_string): New --attribute-fd feature to dump the contents of attribute subpackets for frontends. If --status-fd is also used, then a new status tag ATTRIBUTE is provided for each subpacket. * packet.h, getkey.c (fixup_uidnode, merge_selfsigs_main, merge_selfsigs_subkey), parse-packet.c (setup_user_id): Keep track of the expiration time of a user ID, and while we're at it, use the expired flag from the selfsig rather than reparsing the SIG_EXPIRE subpacket. * photoid.c (generate_photo_id): When adding a new photo ID, showing the photo for confirmation is not safe when noninteractive since the "user" may not be able to dismiss a viewer window. Noted by Timo Schulz. --- g10/ChangeLog | 20 ++++++++++++++ g10/g10.c | 5 ++++ g10/getkey.c | 30 ++++++++++---------- g10/keylist.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ g10/main.h | 1 + g10/packet.h | 6 ++-- g10/parse-packet.c | 2 ++ g10/photoid.c | 25 ++++++++++------- g10/status.c | 1 + g10/status.h | 1 + 10 files changed, 132 insertions(+), 28 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 60ca07349..9ddb871f9 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,23 @@ +2002-06-03 David Shaw + + * main.h, g10.c (main), keylist.c (dump_attribs, set_attrib_fd, + list_keyblock_print, list_keyblock_colon), status.h, status.c + (get_status_string): New --attribute-fd feature to dump the + contents of attribute subpackets for frontends. If --status-fd is + also used, then a new status tag ATTRIBUTE is provided for each + subpacket. + + * packet.h, getkey.c (fixup_uidnode, merge_selfsigs_main, + merge_selfsigs_subkey), parse-packet.c (setup_user_id): Keep track + of the expiration time of a user ID, and while we're at it, use + the expired flag from the selfsig rather than reparsing the + SIG_EXPIRE subpacket. + + * photoid.c (generate_photo_id): When adding a new photo ID, + showing the photo for confirmation is not safe when noninteractive + since the "user" may not be able to dismiss a viewer window. + Noted by Timo Schulz. + 2002-06-03 David Shaw * options.skel: Sample photo viewers for Win32. diff --git a/g10/g10.c b/g10/g10.c index 2fce0633a..1d21f4f43 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -148,6 +148,7 @@ enum cmd_and_opt_values { aNull = 0, oDebug, oDebugAll, oStatusFD, + oAttributeFD, #ifdef __riscos__ oStatusFile, #endif /* __riscos__ */ @@ -410,6 +411,7 @@ static ARGPARSE_OPTS opts[] = { { oDebug, "debug" ,4|16, "@"}, { oDebugAll, "debug-all" ,0, "@"}, { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, + { oAttributeFD, "attribute-fd" ,1, "@" }, #ifdef __riscos__ { oStatusFile, "status-file" ,2, N_("|[file]|write status info to file") }, #endif /* __riscos__ */ @@ -1059,6 +1061,9 @@ main( int argc, char **argv ) case oStatusFD: set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) ); break; + case oAttributeFD: + set_attrib_fd(iobuf_translate_file_handle (pargs.r.ret_int, 1)); + break; #ifdef __riscos__ case oStatusFile: set_status_fd( iobuf_translate_file_handle ( fdopenfile (pargs.r.ret_str, 1), 1) ); diff --git a/g10/getkey.c b/g10/getkey.c index 01d2726c4..eac4d166f 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1118,7 +1118,10 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) uid->created = sig->timestamp; /* this one is okay */ uid->selfsigversion = sig->version; - + /* If we got this far, it's not expired :) */ + uid->is_expired = 0; + uid->expiredate = sig->expiredate; + /* store the key flags in the helper variable for later processing */ uid->help_key_usage = 0; p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); @@ -1276,11 +1279,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) } if( sig->timestamp >= sigdate ) { - const byte *p; - - p = parse_sig_subpkt( sig->hashed, - SIGSUBPKT_SIG_EXPIRE, NULL ); - if ( p && (sig->timestamp + buffer_to_u32(p)) <= curtime ) + if(sig->flags.expired) ; /* signature has expired - ignore it */ else { sigdate = sig->timestamp; @@ -1406,13 +1405,14 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) * one time an email address may become invalid but later * the same email address may become valid again (hired, * fired, hired again). - */ - const byte *p; - - p = parse_sig_subpkt (sig->hashed, - SIGSUBPKT_SIG_EXPIRE, NULL ); - if ( p && (sig->timestamp + buffer_to_u32(p)) <= curtime ) - ; /* signature/revocation has expired - ignore it */ + */ + if(sig->flags.expired) { + /* Expired uids don't get to be primary unless + they are the only uid there is. */ + uidnode->pkt->pkt.user_id->is_primary=0; + uidnode->pkt->pkt.user_id->is_expired=1; + uidnode->pkt->pkt.user_id->expiredate=sig->expiredate; + } else { sigdate = sig->timestamp; signode = k; @@ -1633,9 +1633,7 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) * time */ } else if ( IS_SUBKEY_SIG (sig) && sig->timestamp >= sigdate ) { - p = parse_sig_subpkt (sig->hashed, - SIGSUBPKT_SIG_EXPIRE, NULL ); - if ( p && (sig->timestamp + buffer_to_u32(p)) >= curtime ) + if(sig->flags.expired) ; /* signature has expired - ignore it */ else { sigdate = sig->timestamp; diff --git a/g10/keylist.c b/g10/keylist.c index f91d38439..296de6b5a 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -36,6 +36,7 @@ #include "trustdb.h" #include "main.h" #include "i18n.h" +#include "status.h" static void list_all(int); static void list_one( STRLIST names, int secret); @@ -47,6 +48,8 @@ struct sig_stats int oth_err; }; +static FILE *attrib_fp=NULL; + /**************** * List the keys * If list is NULL, all available keys are listed @@ -336,6 +339,46 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) putchar(':'); } +static void dump_attribs(const PKT_user_id *uid, + PKT_public_key *pk,PKT_secret_key *sk) +{ + int i; + + if(!attrib_fp) + BUG(); + + for(i=0;inumattribs;i++) + { + if(is_status_enabled()) + { + byte array[MAX_FINGERPRINT_LEN], *p; + char buf[(MAX_FINGERPRINT_LEN*2)+90]; + size_t j,n; + + if(pk) + fingerprint_from_pk( pk, array, &n ); + else if(sk) + fingerprint_from_sk( sk, array, &n ); + else + BUG(); + + p = array; + for(j=0; j < n ; j++, p++ ) + sprintf(buf+2*j, "%02X", *p ); + + sprintf(buf+strlen(buf)," %lu %u %u %u %lu %lu %u", + uid->attribs[i].len,uid->attribs[i].type,i+1, + uid->numattribs,(ulong)uid->created,(ulong)uid->expiredate, + ((uid->is_primary?0x01:0)| + (uid->is_revoked?0x02:0)| + (uid->is_expired?0x04:0))); + write_status_text(STATUS_ATTRIBUTE,buf); + } + + fwrite(uid->attribs[i].data,uid->attribs[i].len,1,attrib_fp); + } +} + static void list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) { @@ -377,6 +420,8 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) { + if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL) + dump_attribs(node->pkt->pkt.user_id,pk,sk); /* don't list revoked UIDS unless we are in verbose mode and * signature listing has not been requested */ if ( !opt.verbose && !opt.list_sigs @@ -619,6 +664,8 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) { + if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL) + dump_attribs(node->pkt->pkt.user_id,pk,sk); /* * Fixme: We need a is_valid flag here too */ @@ -950,6 +997,28 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode ) tty_printf ("\n"); } +void set_attrib_fd(int fd) +{ + static int last_fd=-1; + if ( fd != -1 && last_fd == fd ) + return; + if ( attrib_fp && attrib_fp != stdout && attrib_fp != stderr ) + fclose (attrib_fp); + attrib_fp = NULL; + if ( fd == -1 ) + return; + if( fd == 1 ) + attrib_fp = stdout; + else if( fd == 2 ) + attrib_fp = stderr; + else + attrib_fp = fdopen( fd, "w" ); + if( !attrib_fp ) { + log_fatal("can't open fd %d for attribute output: %s\n", + fd, strerror(errno)); + } + last_fd = fd; +} diff --git a/g10/main.h b/g10/main.h index 1ce723301..c22d9f329 100644 --- a/g10/main.h +++ b/g10/main.h @@ -174,6 +174,7 @@ void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque ); void print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode); void show_policy_url(PKT_signature *sig,int indent); void show_notation(PKT_signature *sig,int indent); +void set_attrib_fd(int fd); /*-- verify.c --*/ void print_file_status( int status, const char *name, int what ); diff --git a/g10/packet.h b/g10/packet.h index 70480b292..d530f83f7 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -162,12 +162,14 @@ typedef struct { int len; /* length of the name */ struct user_attribute *attribs; int numattribs; - byte *attrib_data; /* if this is not NULL, the packet is an attribute */ + byte *attrib_data; /* if this is not NULL, the packet is an attribute */ unsigned long attrib_len; int help_key_usage; u32 help_key_expire; int is_primary; - int is_revoked; + int is_revoked; + int is_expired; + u32 expiredate; /* expires at this date or 0 if not at all */ prefitem_t *prefs; /* list of preferences (may be NULL)*/ int mdc_feature; u32 created; /* according to the self-signature */ diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 6d17ff575..54620ece3 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1779,6 +1779,8 @@ static void setup_user_id(PACKET *packet) packet->pkt.user_id->attrib_len = 0; packet->pkt.user_id->is_primary = 0; packet->pkt.user_id->is_revoked = 0; + packet->pkt.user_id->is_expired = 0; + packet->pkt.user_id->expiredate = 0; packet->pkt.user_id->created = 0; packet->pkt.user_id->help_key_usage = 0; packet->pkt.user_id->help_key_expire = 0; diff --git a/g10/photoid.c b/g10/photoid.c index 251ff9907..5fd61fe75 100644 --- a/g10/photoid.c +++ b/g10/photoid.c @@ -120,17 +120,22 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) parse_attribute_subpkts(uid); make_attribute_uidname(uid); - show_photos(uid->attribs,uid->numattribs,pk,NULL); - switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay", - _("Is this photo correct (y/N/q)? "))) + /* Showing the photo is not safe when noninteractive since the + "user" may not be able to dismiss a viewer window! */ + if(opt.command_fd==-1) { - case -1: - goto scram; - case 0: - free_attributes(uid); - m_free(photo); - photo=NULL; - continue; + show_photos(uid->attribs,uid->numattribs,pk,NULL); + switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay", + _("Is this photo correct (y/N/q)? "))) + { + case -1: + goto scram; + case 0: + free_attributes(uid); + m_free(photo); + photo=NULL; + continue; + } } } diff --git a/g10/status.c b/g10/status.c index 5ce15cb28..e0b126b78 100644 --- a/g10/status.c +++ b/g10/status.c @@ -146,6 +146,7 @@ get_status_string ( int no ) case STATUS_SIGEXPIRED : s = "SIGEXPIRED deprecated-use-keyexpired-instead"; break; case STATUS_EXPSIG : s = "EXPSIG"; break; case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break; + case STATUS_ATTRIBUTE : s = "ATTRIBUTE"; break; default: s = "?"; break; } return s; diff --git a/g10/status.h b/g10/status.h index 9886a76de..86e232719 100644 --- a/g10/status.h +++ b/g10/status.h @@ -96,6 +96,7 @@ #define STATUS_SIGEXPIRED 64 #define STATUS_EXPSIG 65 #define STATUS_EXPKEYSIG 66 +#define STATUS_ATTRIBUTE 67 /*-- status.c --*/ void set_status_fd ( int fd );