aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shaw <[email protected]>2001-12-21 23:06:02 +0000
committerDavid Shaw <[email protected]>2001-12-21 23:06:02 +0000
commitd560bdac1860cc04ad4fb8c7dd827dfced596b44 (patch)
tree685a3c3eaafa8bef6562689ec5fafba0942f3a3a
parentNonrevocable key signature support via "nrsign". These sigs can expire, (diff)
downloadgnupg-d560bdac1860cc04ad4fb8c7dd827dfced596b44.tar.gz
gnupg-d560bdac1860cc04ad4fb8c7dd827dfced596b44.zip
Photo ID support (actually generic "attribute packet" support, but there
is only one attribute packet defined thus far, and it's a picture)
-rw-r--r--g10/ChangeLog53
-rw-r--r--g10/Makefile.am8
-rw-r--r--g10/build-packet.c60
-rw-r--r--g10/free-packet.c15
-rw-r--r--g10/g10.c21
-rw-r--r--g10/gpgv.c18
-rw-r--r--g10/keyedit.c106
-rw-r--r--g10/keylist.c11
-rw-r--r--g10/keyserver.c310
-rw-r--r--g10/options.h4
-rw-r--r--g10/options.skel33
-rw-r--r--g10/packet.h28
-rw-r--r--g10/parse-packet.c159
-rw-r--r--g10/sig-check.c14
-rw-r--r--g10/sign.c26
-rw-r--r--g10/trustdb.c8
16 files changed, 523 insertions, 351 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index a29c77318..ff6743ed2 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,5 +1,58 @@
2001-12-21 David Shaw <[email protected]>
+ * 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 <[email protected]>
+
* parse-packet.c (can_handle_critical): Can handle critical
revocation subpackets now.
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
@@ -262,14 +262,25 @@ free_comment( PKT_comment *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)
{
assert (uid->ref > 0);
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;
-
-#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 ();
-#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);
+ struct exec_info *spawn;
- return KEYSERVER_SCHEME_NOT_FOUND;
- }
+#ifdef EXEC_TEMPFILE_ONLY
+ opt.keyserver_options.use_temp_files=1;
+#endif
/* 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);
}
-
- 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)
+ else
{
- log_error(_("%s: can't create: %s\n"),tempfile_in,strerror(errno));
- goto fail;
+ command=m_realloc(command,strlen(command)+
+ strlen(KEYSERVER_ARGS_NOKEEP)+1);
+ strcat(command,KEYSERVER_ARGS_NOKEEP);
}
+
+ ret=exec_write(&spawn,NULL,command,0,0);
}
else
- {
- if(pipe(to)==-1)
- goto fail;
-
- if(pipe(from)==-1)
- goto fail;
-
- if((child=fork())==-1)
- goto fail;
+ ret=exec_write(&spawn,command,NULL,0,0);
- 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;
- }
- }
+ if(ret)
+ 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;i<opt.keyserver_options.verbose;i++)
- fprintf(tochild,"OPTION verbose\n");
+ fprintf(spawn->tochild,"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;i<count;i++)
- fprintf(tochild,"0x%08lX%08lX\n",
+ fprintf(spawn->tochild,"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:[email protected]
@@ -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->photo = m_alloc(sizeof *packet->pkt.user_id + pktlen);
- packet->pkt.user_id->photolen = pktlen;
- p = packet->pkt.user_id->photo;
+ packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + 50);
+
+ 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);