diff --git a/g10/ChangeLog b/g10/ChangeLog index a29c77318..ff6743ed2 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,56 @@ +2001-12-21 David Shaw + + * Makefile.am: add exec.c, exec.h, photoid.c, and photoid.h + + * build-packet.c (build_attribute_subpkt): new function to build + the raw attribute subpacket. Note that attribute subpackets have + the same format as signature subpackets. + + * exec.c: new file with generic exec-a-program functionality. + Used by both photo IDs and keyserver helpers. This is pretty much + the same code that used to be keyserver specific, with some + changes to be usable generically. + + * free-packet.c (free_attributes (new)): function to free an + attribute packet. + + * gpgv.c: added stub show_photo + + * keyedit.c (keyedit_menu, menu_adduid, menu_showphoto): can add a + photo (calls generate_photo_id), or display a photo (calls + show_photo) from the --edit menu. New commands are "addphoto", + and "delphoto" (same as "deluid"). + + * keylist.c (list_keyblock_print): show photos during key list if + --show-photos enabled. + + * keyserver.c (keyserver_spawn): use the generic exec_xxx + functions to call keyserver helper. + + * g10.c, options.h: three new options - --{no-}show-photos, and + --photo-viewer to give the command line to display a picture. + + * options.skel: instructions for the photo viewer + + * parse-packet.c (parse_user_id, setup_user_id (new)): common code + for both user IDs and attribute IDs moved to setup_user_id. + + * parse-packet.c (make_attribute_uidname (new)): constructs a fake + "name" for attribute packets (e.g. "[image of size ...]") + + * parse-packet.c (parse_attribute (replaces parse_photo_id), + parse_attribute_subpkts): Builds an array of individual + attributes. Currently only handles attribute image / type jpeg + subpackets. + + * sign.c (hash_uid): Fix bug in signing attribute (formerly + photo_id) packets. + + * packet.h, and callers: globally change "photo_id" to "attribute" + and add structures for attributes. The packet format is generic + attributes, even though the only attribute type thus far defined + is jpeg. + 2001-12-21 David Shaw * parse-packet.c (can_handle_critical): Can handle critical diff --git a/g10/Makefile.am b/g10/Makefile.am index ac0588ce0..7ee1729df 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -56,7 +56,7 @@ common_source = \ plaintext.c \ sig-check.c \ keylist.c \ - signal.c + signal.c gpg_SOURCES = g10.c \ $(common_source) \ @@ -88,7 +88,11 @@ gpg_SOURCES = g10.c \ pipemode.c \ helptext.c \ keyserver.c \ - keyserver-internal.h + keyserver-internal.h \ + photoid.c photoid.h \ + exec.c exec.h + + gpgv_SOURCES = gpgv.c \ $(common_source) \ diff --git a/g10/build-packet.c b/g10/build-packet.c index ae33b9c04..b8556f5a6 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -81,8 +81,8 @@ build_packet( IOBUF out, PACKET *pkt ) case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break; case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break; case PKT_USER_ID: - if( pkt->pkt.user_id->photo ) - pkttype = PKT_PHOTO_ID; + if( pkt->pkt.user_id->attrib_data ) + pkttype = PKT_ATTRIBUTE; break; default: break; } @@ -92,7 +92,7 @@ build_packet( IOBUF out, PACKET *pkt ) else ctb = 0x80 | ((pkttype & 15)<<2); switch( pkttype ) { - case PKT_PHOTO_ID: + case PKT_ATTRIBUTE: case PKT_USER_ID: rc = do_user_id( out, ctb, pkt->pkt.user_id ); break; @@ -159,7 +159,7 @@ calc_packet_length( PACKET *pkt ) n = calc_plaintext( pkt->pkt.plaintext ); new_ctb = pkt->pkt.plaintext->new_ctb; break; - case PKT_PHOTO_ID: + case PKT_ATTRIBUTE: case PKT_USER_ID: case PKT_COMMENT: case PKT_PUBLIC_KEY: @@ -207,9 +207,9 @@ do_comment( IOBUF out, int ctb, PKT_comment *rem ) static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) { - if( uid->photo ) { - write_header(out, ctb, uid->photolen); - if( iobuf_write( out, uid->photo, uid->photolen ) ) + if( uid->attrib_data ) { + write_header(out, ctb, uid->attrib_len); + if( iobuf_write( out, uid->attrib_data, uid->attrib_len ) ) return G10ERR_WRITE_FILE; } else { @@ -910,6 +910,52 @@ build_sig_subpkt_from_sig( PKT_signature *sig ) } } +void +build_attribute_subpkt(PKT_user_id *uid,byte type, + const void *buf,int buflen, + const void *header,int headerlen) +{ + byte *attrib; + int index; + + if(1+headerlen+buflen>8383) + index=5; + else if(1+headerlen+buflen>191) + index=2; + else + index=1; + + /* realloc uid->attrib_data to the right size */ + + uid->attrib_data=m_realloc(uid->attrib_data, + uid->attrib_len+index+headerlen+buflen); + + attrib=&uid->attrib_data[uid->attrib_len]; + + if(index==5) + { + attrib[0]=255; + attrib[1]=(1+headerlen+buflen) >> 24; + attrib[2]=(1+headerlen+buflen) >> 16; + attrib[3]=(1+headerlen+buflen) >> 8; + attrib[4]=1+headerlen+buflen; + } + else if(index==2) + { + attrib[0]=(1+headerlen+buflen-192) / 256 + 192; + attrib[1]=(1+headerlen+buflen-192) % 256; + } + else + attrib[0]=1+headerlen+buflen; /* Good luck finding a JPEG this small! */ + + attrib[index++]=type; + + /* Tack on our data at the end */ + + memcpy(&attrib[index],header,headerlen); + memcpy(&attrib[index+headerlen],buf,buflen); + uid->attrib_len+=index+headerlen+buflen; +} static int do_signature( IOBUF out, int ctb, PKT_signature *sig ) diff --git a/g10/free-packet.c b/g10/free-packet.c index de5b421b6..f62c7ca03 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -261,6 +261,17 @@ free_comment( PKT_comment *rem ) m_free(rem); } +void +free_attributes(PKT_user_id *uid) +{ + m_free(uid->attribs); + m_free(uid->attrib_data); + + uid->attribs=NULL; + uid->attrib_data=NULL; + uid->attrib_len=0; +} + void free_user_id (PKT_user_id *uid) { @@ -268,8 +279,8 @@ free_user_id (PKT_user_id *uid) if (--uid->ref) return; - if (uid->photo) - m_free (uid->photo); + free_attributes(uid); + if (uid->prefs) m_free (uid->prefs); m_free (uid); diff --git a/g10/g10.c b/g10/g10.c index f594069c0..1fdc99c59 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -194,6 +194,9 @@ enum cmd_and_opt_values { aNull = 0, oComment, oDefaultComment, oThrowKeyid, + oShowPhotos, + oNoShowPhotos, + oPhotoViewer, oForceV3Sigs, oNoForceV3Sigs, oForceV4Certs, @@ -381,6 +384,9 @@ static ARGPARSE_OPTS opts[] = { { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")}, { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")}, { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")}, + { oShowPhotos, "show-photos", 0, N_("Show Photo IDs")}, + { oNoShowPhotos, "no-show-photos", 0, N_("Don't show Photo IDs")}, + { oPhotoViewer, "photo-viewer", 2, N_("Set command line to view Photo IDs")}, { oNotation, "notation-data", 2, N_("|NAME=VALUE|use this notation data")}, { 302, NULL, 0, N_( @@ -827,13 +833,13 @@ main( int argc, char **argv ) { add_to_strlist(&unsafe_files,configname); - /* If any options file is unsafe, then disable the keyserver - code. Since the keyserver code can call an external - program, and the external program to call is set in the - options file, a unsafe options file can lead to an - arbitrary program being run. */ + /* If any options file is unsafe, then disable any external + programs for keyserver calls or photo IDs. Since the + external program to call is set in the options file, a + unsafe options file can lead to an arbitrary program + being run. */ - opt.keyserver_disable=1; + opt.exec_disable=1; } configlineno = 0; @@ -1069,6 +1075,9 @@ main( int argc, char **argv ) case oComment: opt.comment_string = pargs.r.ret_str; break; case oDefaultComment: opt.comment_string = NULL; break; case oThrowKeyid: opt.throw_keyid = 1; break; + case oShowPhotos: opt.show_photos = 1; break; + case oNoShowPhotos: opt.show_photos = 0; break; + case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break; case oForceV3Sigs: opt.force_v3_sigs = 1; break; case oNoForceV3Sigs: opt.force_v3_sigs = 0; break; case oForceV4Certs: opt.force_v4_certs = 1; break; diff --git a/g10/gpgv.c b/g10/gpgv.c index 8720e51d9..87a77447e 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -301,8 +301,10 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, } /* Stub: no decrypting, so no IDEA needed */ -void -idea_cipher_warn( int show ) {} +void idea_cipher_warn( int show ) {} + +/* Stub to avoid linking to photoid.c */ +void show_photo(const struct user_attribute *attr,PKT_public_key *pk) {} /* Stubs to void linking to ../cipher/cipher.c */ int string_to_cipher_algo( const char *string ) { return 0; } @@ -360,15 +362,3 @@ DOTLOCK create_dotlock( const char *file_to_lock ) { return NULL; } int make_dotlock( DOTLOCK h, long timeout ) { return 0;} int release_dotlock( DOTLOCK h ) {return 0;} void remove_lockfiles(void) {} - - - - - - - - - - - - diff --git a/g10/keyedit.c b/g10/keyedit.c index ef4854b51..6f3c4a292 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -32,6 +32,7 @@ #include "iobuf.h" #include "keydb.h" #include "memory.h" +#include "photoid.h" #include "util.h" #include "main.h" #include "trustdb.h" @@ -44,7 +45,7 @@ static void show_prefs( PKT_user_id *uid, int verbose ); static void show_key_with_all_names( KBNODE keyblock, int only_marked, int with_fpr, int with_subkeys, int with_prefs ); static void show_key_and_fingerprint( KBNODE keyblock ); -static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock ); +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 ); @@ -61,6 +62,7 @@ static int count_selected_keys( KBNODE keyblock ); static int menu_revsig( KBNODE keyblock ); static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int enable_disable_key( KBNODE keyblock, int disable ); +static void menu_showphoto( KBNODE keyblock ); #define CONTROL_D ('D' - 'A' + 1) @@ -749,10 +751,10 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, enum cmdids { cmdNONE = 0, cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN, cmdLSIGN, cmdNRSIGN, cmdREVSIG, cmdREVKEY, cmdDELSIG, cmdPRIMARY, - cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY, - cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE, - cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF, - cmdINVCMD, cmdNOP }; + cmdDEBUG, cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, + cmdDELKEY, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, + cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, + cmdUPDPREF, cmdINVCMD, cmdSHOWPHOTO, cmdNOP }; static struct { const char *name; enum cmdids id; int need_sk; @@ -778,7 +780,10 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, { N_("nrsign") , cmdNRSIGN , 0,1,1, N_("sign the key non-revocably") }, { N_("debug") , cmdDEBUG , 0,0,0, NULL }, { N_("adduid") , cmdADDUID , 1,1,0, N_("add a user ID") }, + { N_("addphoto"), cmdADDPHOTO , 1,1,0, N_("add a photo ID") }, { N_("deluid") , cmdDELUID , 0,1,0, N_("delete user ID") }, + /* delphoto is really deluid in disguise */ + { 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_("delsig") , cmdDELSIG , 0,1,0, N_("delete signatures") }, @@ -797,6 +802,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, { N_("revkey") , cmdREVKEY , 1,1,0, N_("revoke a secondary key") }, { N_("disable") , cmdDISABLEKEY, 0,1,0, N_("disable a key") }, { N_("enable") , cmdENABLEKEY , 0,1,0, N_("enable a key") }, + { N_("showphoto"),cmdSHOWPHOTO , 0,0,0, N_("show photo ID") }, { NULL, cmdNONE } }; enum cmdids cmd = 0; @@ -876,7 +882,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, toggle = 0; cur_keyblock = keyblock; for(;;) { /* main loop */ - int i, arg_number; + int i, arg_number, photo; const char *arg_string = ""; char *p; PKT_public_key *pk=keyblock->pkt->pkt.public_key; @@ -907,7 +913,8 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, trim_spaces(answer); } while( *answer == '#' ); - arg_number = 0; /* Yes, here is the init which egcc complains about*/ + arg_number = 0; /* Yes, here is the init which egcc complains about */ + photo = 0; /* This too */ if( !*answer ) cmd = cmdLIST; else if( *answer == CONTROL_D ) @@ -1021,8 +1028,12 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, redisplay = 1; break; + case cmdADDPHOTO: + photo=1; + /* fall through */ + case cmdADDUID: - if( menu_adduid( keyblock, sec_keyblock ) ) { + if( menu_adduid( keyblock, sec_keyblock, photo ) ) { redisplay = 1; sec_modified = modified = 1; merge_keys_and_selfsig( sec_keyblock ); @@ -1199,6 +1210,10 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, } break; + case cmdSHOWPHOTO: + menu_showphoto(keyblock); + break; + case cmdQUIT: if( have_commands ) goto leave; @@ -1492,7 +1507,7 @@ show_key_and_fingerprint( KBNODE keyblock ) * Return true if there is a new user id */ static int -menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock ) +menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) { PKT_user_id *uid; PKT_public_key *pk=NULL; @@ -1503,10 +1518,6 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock ) KBNODE pub_where=NULL, sec_where=NULL; int rc; - uid = generate_user_id(); - if( !uid ) - return 0; - for( node = pub_keyblock; node; pub_where = node, node = node->next ) { if( node->pkt->pkttype == PKT_PUBLIC_KEY ) pk = node->pkt->pkt.public_key; @@ -1523,7 +1534,29 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock ) } if( !node ) /* no subkey */ sec_where = NULL; - assert(pk && sk ); + assert(pk && sk); + + if(photo) { + /* PGP allows only one photo ID per key? */ + for( node = pub_keyblock; node; node = node->next ) + if( node->pkt->pkttype == PKT_USER_ID && + node->pkt->pkt.user_id->attrib_data!=NULL) { + log_error("You may only have one photo ID on a key.\n"); + return 0; + } + + if(pk->version==3) + { + tty_printf(_("\nWARNING: This is a PGP2-style key\n")); + tty_printf(_(" Adding a photo ID may cause some versions " + "of PGP to not accept this key\n")); + } + + uid = generate_photo_id(pk); + } else + uid = generate_user_id(); + if( !uid ) + return 0; rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0, keygen_add_std_prefs, pk ); @@ -1856,8 +1889,6 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ) return 1; } - - static int change_primary_uid_cb ( PKT_signature *sig, void *opaque ) { @@ -2452,3 +2483,46 @@ enable_disable_key( KBNODE keyblock, int disable ) return 0; } + +static void +menu_showphoto( KBNODE keyblock ) +{ + KBNODE node; + int select_all = !count_selected_uids(keyblock); + int count=0; + PKT_public_key *pk=NULL; + u32 keyid[2]; + + /* Look for the public key first. We have to be really, really, + explicit as to which photo this is, and what key it is a UID on + since people may want to sign it. */ + + for( node = keyblock; node; node = node->next ) + { + if( node->pkt->pkttype == PKT_PUBLIC_KEY ) + pk = node->pkt->pkt.public_key; + } + + for( node = keyblock; node; node = node->next ) + { + if( node->pkt->pkttype == PKT_USER_ID ) + { + PKT_user_id *uid = node->pkt->pkt.user_id; + count++; + + if((select_all || (node->flag & NODFLG_SELUID)) && + uid->attribs!=NULL) + { + /* Can this really ever happen? */ + if(pk==NULL) + keyid[1]=0; + else + keyid_from_pk(pk, keyid); + + tty_printf("Displaying photo ID of size %ld for key 0x%08lX " + "(uid %d)\n",uid->attribs->len,(ulong)keyid[1],count); + show_photo(uid->attribs,pk); + } + } + } +} diff --git a/g10/keylist.c b/g10/keylist.c index 49f33ed4f..aed2f6be9 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -30,6 +30,7 @@ #include "errors.h" #include "keydb.h" #include "memory.h" +#include "photoid.h" #include "util.h" #include "ttyio.h" #include "trustdb.h" @@ -352,6 +353,10 @@ list_keyblock_print ( KBNODE keyblock, int secret ) print_key_data( pk, keyid ); any = 1; } + + if(opt.show_photos && node->pkt->pkt.user_id->attribs!=NULL && + node->pkt->pkt.user_id->attribs->type==ATTRIB_JPEG) + show_photo(node->pkt->pkt.user_id->attribs,pk); } else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { u32 keyid2[2]; @@ -576,10 +581,10 @@ list_keyblock_colon( KBNODE keyblock, int secret ) byte namehash[20]; if( pk && !ulti_hack ) { - if( node->pkt->pkt.user_id->photo ) + if( node->pkt->pkt.user_id->attrib_data ) rmd160_hash_buffer( namehash, - node->pkt->pkt.user_id->photo, - node->pkt->pkt.user_id->photolen); + node->pkt->pkt.user_id->attrib_data, + node->pkt->pkt.user_id->attrib_len); else rmd160_hash_buffer( namehash, node->pkt->pkt.user_id->name, diff --git a/g10/keyserver.c b/g10/keyserver.c index 7e5f28731..eb1fc0686 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -34,21 +34,13 @@ #include "options.h" #include "memory.h" #include "keydb.h" -#include "cipher.h" #include "status.h" +#include "exec.h" #include "i18n.h" #include "util.h" #include "main.h" #include "hkp.h" -#ifndef HAVE_MKDTEMP -char *mkdtemp(char *template); -#endif - -#if !(defined(HAVE_FORK) && defined(HAVE_PIPE)) -#define KEYSERVER_TEMPFILE_ONLY -#endif - #define KEYSERVER_PROTO_VERSION 0 #define GET 0 @@ -74,7 +66,7 @@ parse_keyserver_options(char *options) opt.keyserver_options.include_disabled=1; else if(strcasecmp(tok,"no-include-disabled")==0) opt.keyserver_options.include_disabled=0; -#ifdef KEYSERVER_TEMPFILE_ONLY +#ifdef EXEC_TEMPFILE_ONLY else if(strcasecmp(tok,"use-temp-files")==0 || strcasecmp(tok,"no-use-temp-files")==0) log_info(_("Warning: keyserver option \"%s\" is not used " @@ -261,167 +253,75 @@ print_keyinfo(int count,char *keystring,u32 *keyid) return 0; } +#define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\"" +#define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\"" static int -keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) +keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count,int *prog) { - int ret=KEYSERVER_INTERNAL_ERROR,i,to[2]={-1,-1},from[2]={-1,-1}; - pid_t child=0; + int ret=0,i,gotversion=0; STRLIST temp; unsigned int maxlen=256,buflen; - char *filename=NULL,*tempfile_in=NULL,*tempfile_out=NULL,*searchstr=NULL; - char *tempdir=NULL; + char *command=NULL,*searchstr=NULL; byte *line=NULL; - FILE *tochild=NULL; - IOBUF fromchild=NULL; - int gotversion=0,madedir=0; + struct exec_info *spawn; -#ifndef __MINGW32__ - /* Don't allow to be setuid when we are going to create temporary - files or directories - yes, this is a bit paranoid */ - if (getuid() != geteuid() ) - BUG (); +#ifdef EXEC_TEMPFILE_ONLY + opt.keyserver_options.use_temp_files=1; #endif - if(opt.keyserver_disable && !opt.no_perm_warn) - { - log_info(_("keyserver scheme \"%s\" disabled due to unsafe " - "options file permissions\n"),opt.keyserver_scheme); - - return KEYSERVER_SCHEME_NOT_FOUND; - } - /* Build the filename for the helper to execute */ - filename=m_alloc(strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1); - - - strcpy(filename,"gpgkeys_"); - strcat(filename,opt.keyserver_scheme); + command=m_alloc(strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1); + strcpy(command,"gpgkeys_"); + strcat(command,opt.keyserver_scheme); if(opt.keyserver_options.use_temp_files) { - const char *tmp=get_temp_dir(); - - tempdir=m_alloc(strlen(tmp)+1+10+1); - sprintf(tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp); - - if(mkdtemp(tempdir)==NULL) + if(opt.keyserver_options.keep_temp_files) { - log_error(_("%s: can't create temp directory: %s\n"), - tempdir,strerror(errno)); - goto fail; + command=m_realloc(command,strlen(command)+ + strlen(KEYSERVER_ARGS_KEEP)+1); + strcat(command,KEYSERVER_ARGS_KEEP); + } + else + { + command=m_realloc(command,strlen(command)+ + strlen(KEYSERVER_ARGS_NOKEEP)+1); + strcat(command,KEYSERVER_ARGS_NOKEEP); } - madedir=1; - - tempfile_in=m_alloc(strlen(tempdir)+1+10+1); - sprintf(tempfile_in,"%s" DIRSEP_S "ksrvin" EXTSEP_S "txt",tempdir); - - tempfile_out=m_alloc(strlen(tempdir)+1+11+1); - sprintf(tempfile_out,"%s" DIRSEP_S "ksrvout" EXTSEP_S "txt",tempdir); - - tochild=fopen(tempfile_in,"w"); - if(tochild==NULL) - { - log_error(_("%s: can't create: %s\n"),tempfile_in,strerror(errno)); - goto fail; - } + ret=exec_write(&spawn,NULL,command,0,0); } else - { - if(pipe(to)==-1) - goto fail; + ret=exec_write(&spawn,command,NULL,0,0); - if(pipe(from)==-1) - goto fail; + if(ret) + goto fail; - if((child=fork())==-1) - goto fail; - - if(child==0) - { - /* I'm the child */ - - /* implied close of STDERR */ - if(dup2(STDOUT_FILENO,STDERR_FILENO)==-1) - _exit(KEYSERVER_INTERNAL_ERROR); - - close(from[0]); - from[0]=-1; - - /* implied close of STDOUT */ - if(dup2(from[1],STDOUT_FILENO)==-1) - _exit(KEYSERVER_INTERNAL_ERROR); - - close(to[1]); - to[1]=-1; - - /* implied close of STDIN */ - if(dup2(to[0],STDIN_FILENO)==-1) - _exit(KEYSERVER_INTERNAL_ERROR); - - execlp(filename,filename,NULL); - - /* If we get this far the exec failed. Clean up and return. */ - - if(opt.keyserver_options.verbose>2) - log_error(_("unable to execute %s: %s\n"), - filename,strerror(errno)); - - if(errno==ENOENT) - _exit(KEYSERVER_SCHEME_NOT_FOUND); - - _exit(KEYSERVER_INTERNAL_ERROR); - } - - /* I'm the parent */ - - close(to[0]); - to[0]=-1; - - tochild=fdopen(to[1],"w"); - if(tochild==NULL) - { - ret=G10ERR_WRITE_FILE; - close(to[1]); - goto fail; - } - - close(from[1]); - from[1]=-1; - - fromchild=iobuf_fdopen(from[0],"r"); - if(fromchild==NULL) - { - ret=G10ERR_READ_FILE; - goto fail; - } - } - - fprintf(tochild,"# This is a gpg keyserver communications file\n"); - fprintf(tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION); - fprintf(tochild,"PROGRAM %s\n",VERSION); - fprintf(tochild,"HOST %s\n",opt.keyserver_host); + fprintf(spawn->tochild,"# This is a gpg keyserver communications file\n"); + fprintf(spawn->tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION); + fprintf(spawn->tochild,"PROGRAM %s\n",VERSION); + fprintf(spawn->tochild,"HOST %s\n",opt.keyserver_host); if(atoi(opt.keyserver_port)>0) - fprintf(tochild,"PORT %s\n",opt.keyserver_port); + fprintf(spawn->tochild,"PORT %s\n",opt.keyserver_port); /* Write options */ - fprintf(tochild,"OPTION %sinclude-revoked\n", + fprintf(spawn->tochild,"OPTION %sinclude-revoked\n", opt.keyserver_options.include_revoked?"":"no-"); - fprintf(tochild,"OPTION %sinclude-disabled\n", + fprintf(spawn->tochild,"OPTION %sinclude-disabled\n", opt.keyserver_options.include_disabled?"":"no-"); for(i=0;itochild,"OPTION verbose\n"); temp=opt.keyserver_options.other; for(;temp;temp=temp->next) - fprintf(tochild,"OPTION %s\n",temp->d); + fprintf(spawn->tochild,"OPTION %s\n",temp->d); switch(action) { @@ -429,15 +329,15 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) { int i; - fprintf(tochild,"COMMAND GET\n\n"); + fprintf(spawn->tochild,"COMMAND GET\n\n"); /* Which keys do we want? */ for(i=0;itochild,"0x%08lX%08lX\n", (ulong)kidlist[i][0],(ulong)kidlist[i][1]); - fprintf(tochild,"\n"); + fprintf(spawn->tochild,"\n"); break; } @@ -447,7 +347,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) STRLIST key,temp; /* Note the extra \n here to send an empty keylist block */ - fprintf(tochild,"COMMAND SEND\n\n\n"); + fprintf(spawn->tochild,"COMMAND SEND\n\n\n"); for(key=list;key!=NULL;key=key->next) { @@ -467,10 +367,10 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) { iobuf_flush_temp(buffer); - fprintf(tochild,"KEY %s BEGIN\n",key->d); + fprintf(spawn->tochild,"KEY %s BEGIN\n",key->d); fwrite(iobuf_get_temp_buffer(buffer), - iobuf_get_temp_length(buffer),1,tochild); - fprintf(tochild,"KEY %s END\n",key->d); + iobuf_get_temp_length(buffer),1,spawn->tochild); + fprintf(spawn->tochild,"KEY %s END\n",key->d); iobuf_close(buffer); } @@ -485,14 +385,14 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) { STRLIST key; - fprintf(tochild,"COMMAND SEARCH\n\n"); + fprintf(spawn->tochild,"COMMAND SEARCH\n\n"); /* Which keys do we want? Remember that the gpgkeys_ program is going to lump these together into a search string. */ for(key=list;key!=NULL;key=key->next) { - fprintf(tochild,"%s\n",key->d); + fprintf(spawn->tochild,"%s\n",key->d); if(key!=list) { searchstr=m_realloc(searchstr, @@ -508,7 +408,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) strcat(searchstr,key->d); } - fprintf(tochild,"\n"); + fprintf(spawn->tochild,"\n"); break; } @@ -518,52 +418,16 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) break; } - /* Done sending */ - fclose(tochild); - tochild=NULL; - to[1]=-1; - - if(opt.keyserver_options.use_temp_files) - { - char *command=m_alloc(strlen(filename)+2+ - strlen(tempfile_in)+6+ - strlen(tempfile_out)+2); - - sprintf(command,"%s -o \"%s\" \"%s\"",filename,tempfile_out,tempfile_in); - - ret=system(command); - - m_free(command); - - ret=WEXITSTATUS(ret); - - if(ret==127) - { - log_error(_("unable to exec keyserver program\n")); - goto fail; - } - - if(ret==-1) - { - log_error(_("internal system error while calling keyserver: %s\n"), - strerror(errno)); - goto fail; - } - - fromchild=iobuf_open(tempfile_out); - if(fromchild==NULL) - { - log_error(_("unable to read keyserver response: %s\n"), - strerror(errno)); - goto fail; - } - } + /* Done sending, so start reading. */ + ret=exec_read(spawn); + if(ret) + goto fail; /* Now handle the response */ do { - if(iobuf_read_line(fromchild,&line,&buflen,&maxlen)==0) + if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0) { ret=G10ERR_READ_FILE; goto fail; /* i.e. EOF */ @@ -612,7 +476,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) do this could be to continue parsing this line-by-line and make a temp iobuf for each key. */ - import_keys_stream(fromchild, + import_keys_stream(spawn->fromchild, opt.keyserver_options.fast_import,stats_handle); import_print_stats(stats_handle); @@ -634,7 +498,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) /* Look for the COUNT line */ do { - if(iobuf_read_line(fromchild,&line,&buflen,&maxlen)==0) + if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0) { ret=G10ERR_READ_FILE; goto fail; /* i.e. EOF */ @@ -642,7 +506,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) } while(sscanf(line,"COUNT %d\n",&count)!=1); - keyserver_search_prompt(fromchild,count,searchstr); + keyserver_search_prompt(spawn->fromchild,count,searchstr); break; } @@ -652,54 +516,9 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) break; } - iobuf_close(fromchild); - fromchild=NULL; - ret=0; + *prog=exec_finish(spawn); fail: - if(tochild!=NULL) - { - fclose(tochild); - to[1]=-1; - } - - if(fromchild!=NULL) - { - iobuf_close(fromchild); - from[0]=-1; - } - - if(from[0]>-1) - close(from[0]); - if(from[1]>-1) - close(from[1]); - - if(to[0]>-1) - close(to[0]); - if(to[1]>-1) - close(to[1]); - - if(child>0) - { - int rc; - - waitpid(child,&rc,0); - if(ret==0 && WIFEXITED(rc)) - ret=WEXITSTATUS(rc); - } - - m_free(filename); - - if(madedir && !opt.keyserver_options.keep_temp_files) - { - unlink(tempfile_in); - unlink(tempfile_out); - rmdir(tempdir); - } - - m_free(tempfile_in); - m_free(tempfile_out); - m_free(tempdir); return ret; } @@ -707,11 +526,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count) static int keyserver_work(int action,STRLIST list,u32 (*kidlist)[2],int count) { - int rc=0; - -#ifdef KEYSERVER_TEMPFILE_ONLY - opt.keyserver_options.use_temp_files=1; -#endif + int rc=0,ret=0; if(opt.keyserver_scheme==NULL || opt.keyserver_host==NULL || @@ -749,10 +564,13 @@ keyserver_work(int action,STRLIST list,u32 (*kidlist)[2],int count) /* It's not the internal HKP code, so try and spawn a handler for it */ - if((rc=keyserver_spawn(action,list,kidlist,count))) + if((rc=keyserver_spawn(action,list,kidlist,count,&ret))==0) { - switch(rc) + switch(ret) { + case KEYSERVER_OK: + break; + case KEYSERVER_SCHEME_NOT_FOUND: log_error(_("no handler for keyserver scheme \"%s\"\n"), opt.keyserver_scheme); @@ -767,6 +585,12 @@ keyserver_work(int action,STRLIST list,u32 (*kidlist)[2],int count) /* This is not the best error code for this */ return G10ERR_INVALID_URI; } + else + { + log_error(_("keyserver communications error\n")); + + return rc; + } return 0; } diff --git a/g10/options.h b/g10/options.h index 4f22f2f33..a9c14c1fa 100644 --- a/g10/options.h +++ b/g10/options.h @@ -85,6 +85,8 @@ struct { const char *set_filename; const char *comment_string; int throw_keyid; + int show_photos; + const char *photo_viewer; int s2k_mode; int s2k_digest_algo; int s2k_cipher_algo; @@ -104,7 +106,7 @@ struct { int keep_temp_files:1; STRLIST other; } keyserver_options; - int keyserver_disable; + int exec_disable; int no_perm_warn; char *temp_dir; int no_encrypt_to; diff --git a/g10/options.skel b/g10/options.skel index 6f262ac12..6e4a5a1a2 100644 --- a/g10/options.skel +++ b/g10/options.skel @@ -115,7 +115,7 @@ lock-once # proxies (honor-http-proxy) # # Most users just set the name and type of their preferred keyserver. -# Most servers do syncronize with each other and DNS round-robin may +# Most servers do synchronize with each other and DNS round-robin may # give you a quasi-random server each time. #keyserver mailto:pgp-public-keys@keys.nl.pgp.net @@ -151,7 +151,32 @@ lock-once #auto-key-retrieve -# The environment variable http_proxy is only used when the -# this option is set. +# Uncomment this line to display photo user IDs in key listings +#show-photos -#honor-http-proxy +# Use this program to display photo user IDs +# +# %i is expanded to a temporary file that contains the photo. +# %I is the same as %i, but the file isn't deleted afterwards by GnuPG. +# %k is expanded to the key ID of the key. +# %K is expanded to the long OpenPGP key ID of the key. +# %f is expanded to the fingerprint of the key. +# %% is %, of course. +# +# If %i or %I are not present, then the photo is supplied to the +# viewer on standard input. Standard input is the best way to do +# this, as it avoids the time and effort in generating and then +# cleaning up a secure temp file. +# +# The default program is "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin" +# +# Some other viewers: +# photo-viewer "xv -name \"KeyID 0x%k\" -" +# photo-viewer "ee %i" +# photo-viewer "display -title 'KeyID 0x%k'" +# +# This one saves a copy of the photo ID in your home directory: +# photo-viewer "cat > ~/photoid-for-key-%k.jpg" +# +# Use your MIME handler to view photos: +# photo-viewer "metamail -q -d -b -c image/jpeg -s 'KeyID 0x%k' -f GnuPG" diff --git a/g10/packet.h b/g10/packet.h index de18d9695..110ed5e82 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -46,7 +46,7 @@ typedef enum { PKT_USER_ID =13, /* user id packet */ PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */ PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */ - PKT_PHOTO_ID =17, /* PGP's photo ID */ + PKT_ATTRIBUTE =17, /* PGP's attribute packet */ PKT_ENCRYPTED_MDC =18, /* integrity protected encrypted data */ PKT_MDC =19, /* manipulaion detection code packet */ PKT_COMMENT =61, /* new comment packet (private) */ @@ -140,12 +140,26 @@ typedef struct { MPI data[PUBKEY_MAX_NSIG]; } PKT_signature; +typedef enum +{ + ATTRIB_UNKNOWN, + ATTRIB_JPEG +} attribtype_t; + +/* This is the cooked form of attributes */ +struct user_attribute { + attribtype_t type; + const byte *data; + unsigned long len; +}; typedef struct { int ref; /* reference counter */ - int len; /* length of the name */ - char *photo; /* if this is not NULL, the packet is a photo ID */ - int photolen; /* and the length of the photo */ + 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 */ + unsigned long attrib_len; int help_key_usage; u32 help_key_expire; int is_primary; @@ -367,6 +381,8 @@ const byte *parse_sig_subpkt ( const subpktarea_t *buffer, const byte *parse_sig_subpkt2 ( PKT_signature *sig, sigsubpkttype_t reqtype, size_t *ret_n ); +int parse_attribute_subpkts(PKT_user_id *uid); +void make_attribute_uidname(PKT_user_id *uid); PACKET *create_gpg_control ( ctrlpkttype_t type, const byte *data, size_t datalen ); @@ -379,6 +395,9 @@ void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, const byte *buffer, size_t buflen ); void build_sig_subpkt_from_sig( PKT_signature *sig ); int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type ); +void build_attribute_subpkt(PKT_user_id *uid,byte type, + const void *buf,int buflen, + const void *header,int headerlen); /*-- free-packet.c --*/ void free_symkey_enc( PKT_symkey_enc *enc ); @@ -389,6 +408,7 @@ void release_public_key_parts( PKT_public_key *pk ); void free_public_key( PKT_public_key *key ); void release_secret_key_parts( PKT_secret_key *sk ); void free_secret_key( PKT_secret_key *sk ); +void free_attributes(PKT_user_id *uid); void free_user_id( PKT_user_id *uid ); void free_comment( PKT_comment *rem ); void free_packet( PACKET *pkt ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 1de7c85c6..60c45b56b 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -61,7 +61,7 @@ static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen, byte *hdr, int hdrlen, PACKET *packet ); static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); @@ -438,9 +438,9 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, case PKT_USER_ID: rc = parse_user_id(inp, pkttype, pktlen, pkt ); break; - case PKT_PHOTO_ID: + case PKT_ATTRIBUTE: pkt->pkttype = pkttype = PKT_USER_ID; /* we store it in the userID */ - rc = parse_photo_id(inp, pkttype, pktlen, pkt); + rc = parse_attribute(inp, pkttype, pktlen, pkt); break; case PKT_OLD_COMMENT: case PKT_COMMENT: @@ -1657,6 +1657,98 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, return rc; } +/* Attribute subpackets have the same format as v4 signature + subpackets. This is not part of OpenPGP, but is done in several + versions of PGP nevertheless. */ +int +parse_attribute_subpkts(PKT_user_id *uid) +{ + size_t n; + int count=0; + struct user_attribute *attribs=NULL; + const byte *buffer=uid->attrib_data; + int buflen=uid->attrib_len; + byte type; + + m_free(uid->attribs); + + while(buflen) + { + n = *buffer++; buflen--; + if( n == 255 ) { /* 4 byte length header */ + if( buflen < 4 ) + goto too_short; + n = (buffer[0] << 24) | (buffer[1] << 16) + | (buffer[2] << 8) | buffer[3]; + buffer += 4; + buflen -= 4; + } + else if( n >= 192 ) { /* 2 byte special encoded length header */ + if( buflen < 2 ) + goto too_short; + n = (( n - 192 ) << 8) + *buffer + 192; + buffer++; + buflen--; + } + if( buflen < n ) + goto too_short; + + attribs=m_realloc(attribs,(count+1)*sizeof(struct user_attribute)); + memset(&attribs[count],0,sizeof(struct user_attribute)); + + type=*buffer; + buffer++; + buflen--; + n--; + + /* In order: is it an image, is it large enough to carry the + image header, is it version 1, and is it a JPEG? */ + if(type==1 && n>=16 && buffer[2]==1 && buffer[3]==1) + { + /* For historical reasons (i.e. "oops!"), headerlen is + little endian. */ + u16 headerlen=(buffer[1]<<8) | buffer[0]; + + attribs[count].type=ATTRIB_JPEG; + + buffer+=headerlen; + buflen-=headerlen; + n-=headerlen; + } + else + attribs[count].type=ATTRIB_UNKNOWN; + + attribs[count].data=buffer; + attribs[count].len=n; + buffer+=n; + buflen-=n; + count++; + } + + uid->attribs=attribs; + uid->numattribs=count; + return count; + + too_short: + log_error("buffer shorter than attribute subpacket\n"); + uid->attribs=attribs; + uid->numattribs=count; + return count; +} + +static void setup_user_id(PACKET *packet) +{ + packet->pkt.user_id->ref = 1; + packet->pkt.user_id->attribs = NULL; + packet->pkt.user_id->attrib_data = NULL; + 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->created = 0; + packet->pkt.user_id->help_key_usage = 0; + packet->pkt.user_id->help_key_expire = 0; + packet->pkt.user_id->prefs = NULL; +} static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) @@ -1664,16 +1756,9 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) byte *p; packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + pktlen); - packet->pkt.user_id->ref = 1; packet->pkt.user_id->len = pktlen; - packet->pkt.user_id->photo = NULL; - packet->pkt.user_id->photolen = 0; - packet->pkt.user_id->is_primary = 0; - packet->pkt.user_id->is_revoked = 0; - packet->pkt.user_id->created = 0; - packet->pkt.user_id->help_key_usage = 0; - packet->pkt.user_id->help_key_expire = 0; - packet->pkt.user_id->prefs = NULL; + + setup_user_id(packet); p = packet->pkt.user_id->name; for( ; pktlen; pktlen--, p++ ) @@ -1695,35 +1780,45 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) return 0; } +void +make_attribute_uidname(PKT_user_id *uid) +{ + /* List the first attribute as the "user id" */ + if(uid->attribs) + sprintf( uid->name, "[%s of size %lu]", + uid->attribs->type==ATTRIB_JPEG?"image":"unknown attribute", + uid->attribs->len); + else + sprintf( uid->name, "[bad attribute of size %lu]", + uid->attrib_len ); + + uid->len = strlen(uid->name); +} -/**************** - * PGP generates a packet of type 17. We assume this is a photo ID and - * simply store it here as a comment packet. - */ static int -parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; - packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + 30); - packet->pkt.user_id->ref = 1; - sprintf( packet->pkt.user_id->name, "[image of size %lu]", pktlen ); - packet->pkt.user_id->len = strlen(packet->pkt.user_id->name); - packet->pkt.user_id->is_primary = 0; - packet->pkt.user_id->is_revoked = 0; - packet->pkt.user_id->created = 0; - packet->pkt.user_id->help_key_usage = 0; - packet->pkt.user_id->help_key_expire = 0; - packet->pkt.user_id->prefs = NULL; + packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + 50); - packet->pkt.user_id->photo = m_alloc(sizeof *packet->pkt.user_id + pktlen); - packet->pkt.user_id->photolen = pktlen; - p = packet->pkt.user_id->photo; + setup_user_id(packet); + + packet->pkt.user_id->attrib_data = m_alloc(pktlen); + packet->pkt.user_id->attrib_len = pktlen; + p = packet->pkt.user_id->attrib_data; for( ; pktlen; pktlen--, p++ ) *p = iobuf_get_noeof(inp); + /* Now parse out the individual attribute subpackets. This is + somewhat pointless since there is only one currently defined + attribute type (jpeg), but it is correct by the spec. */ + parse_attribute_subpkts(packet->pkt.user_id); + + make_attribute_uidname(packet->pkt.user_id); + if( list_mode ) { - printf(":photo_id packet: %s\n", packet->pkt.user_id->name ); + printf(":attribute packet: %s\n", packet->pkt.user_id->name ); } return 0; } diff --git a/g10/sig-check.c b/g10/sig-check.c index 754bc2fd7..6946eecf2 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -323,17 +323,17 @@ hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig ) PKT_user_id *uid = unode->pkt->pkt.user_id; assert( unode->pkt->pkttype == PKT_USER_ID ); - if( uid->photo ) { + if( uid->attrib_data ) { if( sig->version >=4 ) { byte buf[5]; - buf[0] = 0xd1; /* packet of type 17 */ - buf[1] = uid->photolen >> 24; /* always use 4 length bytes */ - buf[2] = uid->photolen >> 16; - buf[3] = uid->photolen >> 8; - buf[4] = uid->photolen; + buf[0] = 0xd1; /* packet of type 17 */ + buf[1] = uid->attrib_len >> 24; /* always use 4 length bytes */ + buf[2] = uid->attrib_len >> 16; + buf[3] = uid->attrib_len >> 8; + buf[4] = uid->attrib_len; md_write( md, buf, 5 ); } - md_write( md, uid->photo, uid->photolen ); + md_write( md, uid->attrib_data, uid->attrib_len ); } else { if( sig->version >=4 ) { diff --git a/g10/sign.c b/g10/sign.c index 48a506901..313433517 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -110,14 +110,28 @@ hash_uid (MD_HANDLE md, int sigversion, const PKT_user_id *uid) { if ( sigversion >= 4 ) { byte buf[5]; - buf[0] = 0xb4; /* indicates a userid packet */ - buf[1] = uid->len >> 24; /* always use 4 length bytes */ - buf[2] = uid->len >> 16; - buf[3] = uid->len >> 8; - buf[4] = uid->len; + + if(uid->attrib_data) { + buf[0] = 0xd1; /* indicates an attribute packet */ + buf[1] = uid->attrib_len >> 24; /* always use 4 length bytes */ + buf[2] = uid->attrib_len >> 16; + buf[3] = uid->attrib_len >> 8; + buf[4] = uid->attrib_len; + } + else { + buf[0] = 0xb4; /* indicates a userid packet */ + buf[1] = uid->len >> 24; /* always use 4 length bytes */ + buf[2] = uid->len >> 16; + buf[3] = uid->len >> 8; + buf[4] = uid->len; + } md_write( md, buf, 5 ); } - md_write (md, uid->name, uid->len ); + + if(uid->attrib_data) + md_write (md, uid->attrib_data, uid->attrib_len ); + else + md_write (md, uid->name, uid->len ); } diff --git a/g10/trustdb.c b/g10/trustdb.c index 9afc1bf8e..ab5d1a488 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -951,8 +951,8 @@ store_validation_status (int depth, KBNODE keyblock) if (status) { - if( uid->photo ) - rmd160_hash_buffer (namehash, uid->photo, uid->photolen); + if( uid->attrib_data ) + rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len); else rmd160_hash_buffer (namehash, uid->name, uid->len ); @@ -1373,8 +1373,8 @@ validate_keys (int interactive) byte namehash[20]; PKT_user_id *uid = node->pkt->pkt.user_id; - if( uid->photo ) - rmd160_hash_buffer (namehash, uid->photo, uid->photolen); + if( uid->attrib_data ) + rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len); else rmd160_hash_buffer (namehash, uid->name, uid->len ); update_validity (pk, namehash, 0, TRUST_ULTIMATE);