mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-10 13:04:23 +01:00
Photo ID support (actually generic "attribute packet" support, but there
is only one attribute packet defined thus far, and it's a picture)
This commit is contained in:
parent
ca058399b0
commit
d560bdac18
@ -1,3 +1,56 @@
|
|||||||
|
2001-12-21 David Shaw <dshaw@jabberwocky.com>
|
||||||
|
|
||||||
|
* 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 <dshaw@jabberwocky.com>
|
2001-12-21 David Shaw <dshaw@jabberwocky.com>
|
||||||
|
|
||||||
* parse-packet.c (can_handle_critical): Can handle critical
|
* parse-packet.c (can_handle_critical): Can handle critical
|
||||||
|
@ -56,7 +56,7 @@ common_source = \
|
|||||||
plaintext.c \
|
plaintext.c \
|
||||||
sig-check.c \
|
sig-check.c \
|
||||||
keylist.c \
|
keylist.c \
|
||||||
signal.c
|
signal.c
|
||||||
|
|
||||||
gpg_SOURCES = g10.c \
|
gpg_SOURCES = g10.c \
|
||||||
$(common_source) \
|
$(common_source) \
|
||||||
@ -88,7 +88,11 @@ gpg_SOURCES = g10.c \
|
|||||||
pipemode.c \
|
pipemode.c \
|
||||||
helptext.c \
|
helptext.c \
|
||||||
keyserver.c \
|
keyserver.c \
|
||||||
keyserver-internal.h
|
keyserver-internal.h \
|
||||||
|
photoid.c photoid.h \
|
||||||
|
exec.c exec.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gpgv_SOURCES = gpgv.c \
|
gpgv_SOURCES = gpgv.c \
|
||||||
$(common_source) \
|
$(common_source) \
|
||||||
|
@ -81,8 +81,8 @@ build_packet( IOBUF out, PACKET *pkt )
|
|||||||
case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break;
|
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_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break;
|
||||||
case PKT_USER_ID:
|
case PKT_USER_ID:
|
||||||
if( pkt->pkt.user_id->photo )
|
if( pkt->pkt.user_id->attrib_data )
|
||||||
pkttype = PKT_PHOTO_ID;
|
pkttype = PKT_ATTRIBUTE;
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ build_packet( IOBUF out, PACKET *pkt )
|
|||||||
else
|
else
|
||||||
ctb = 0x80 | ((pkttype & 15)<<2);
|
ctb = 0x80 | ((pkttype & 15)<<2);
|
||||||
switch( pkttype ) {
|
switch( pkttype ) {
|
||||||
case PKT_PHOTO_ID:
|
case PKT_ATTRIBUTE:
|
||||||
case PKT_USER_ID:
|
case PKT_USER_ID:
|
||||||
rc = do_user_id( out, ctb, pkt->pkt.user_id );
|
rc = do_user_id( out, ctb, pkt->pkt.user_id );
|
||||||
break;
|
break;
|
||||||
@ -159,7 +159,7 @@ calc_packet_length( PACKET *pkt )
|
|||||||
n = calc_plaintext( pkt->pkt.plaintext );
|
n = calc_plaintext( pkt->pkt.plaintext );
|
||||||
new_ctb = pkt->pkt.plaintext->new_ctb;
|
new_ctb = pkt->pkt.plaintext->new_ctb;
|
||||||
break;
|
break;
|
||||||
case PKT_PHOTO_ID:
|
case PKT_ATTRIBUTE:
|
||||||
case PKT_USER_ID:
|
case PKT_USER_ID:
|
||||||
case PKT_COMMENT:
|
case PKT_COMMENT:
|
||||||
case PKT_PUBLIC_KEY:
|
case PKT_PUBLIC_KEY:
|
||||||
@ -207,9 +207,9 @@ do_comment( IOBUF out, int ctb, PKT_comment *rem )
|
|||||||
static int
|
static int
|
||||||
do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
|
do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
|
||||||
{
|
{
|
||||||
if( uid->photo ) {
|
if( uid->attrib_data ) {
|
||||||
write_header(out, ctb, uid->photolen);
|
write_header(out, ctb, uid->attrib_len);
|
||||||
if( iobuf_write( out, uid->photo, uid->photolen ) )
|
if( iobuf_write( out, uid->attrib_data, uid->attrib_len ) )
|
||||||
return G10ERR_WRITE_FILE;
|
return G10ERR_WRITE_FILE;
|
||||||
}
|
}
|
||||||
else {
|
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
|
static int
|
||||||
do_signature( IOBUF out, int ctb, PKT_signature *sig )
|
do_signature( IOBUF out, int ctb, PKT_signature *sig )
|
||||||
|
@ -261,6 +261,17 @@ free_comment( PKT_comment *rem )
|
|||||||
m_free(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
|
void
|
||||||
free_user_id (PKT_user_id *uid)
|
free_user_id (PKT_user_id *uid)
|
||||||
{
|
{
|
||||||
@ -268,8 +279,8 @@ free_user_id (PKT_user_id *uid)
|
|||||||
if (--uid->ref)
|
if (--uid->ref)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (uid->photo)
|
free_attributes(uid);
|
||||||
m_free (uid->photo);
|
|
||||||
if (uid->prefs)
|
if (uid->prefs)
|
||||||
m_free (uid->prefs);
|
m_free (uid->prefs);
|
||||||
m_free (uid);
|
m_free (uid);
|
||||||
|
21
g10/g10.c
21
g10/g10.c
@ -194,6 +194,9 @@ enum cmd_and_opt_values { aNull = 0,
|
|||||||
oComment,
|
oComment,
|
||||||
oDefaultComment,
|
oDefaultComment,
|
||||||
oThrowKeyid,
|
oThrowKeyid,
|
||||||
|
oShowPhotos,
|
||||||
|
oNoShowPhotos,
|
||||||
|
oPhotoViewer,
|
||||||
oForceV3Sigs,
|
oForceV3Sigs,
|
||||||
oNoForceV3Sigs,
|
oNoForceV3Sigs,
|
||||||
oForceV4Certs,
|
oForceV4Certs,
|
||||||
@ -381,6 +384,9 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
{ oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
|
{ oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
|
||||||
{ oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
|
{ oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
|
||||||
{ oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
|
{ 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")},
|
{ oNotation, "notation-data", 2, N_("|NAME=VALUE|use this notation data")},
|
||||||
|
|
||||||
{ 302, NULL, 0, N_(
|
{ 302, NULL, 0, N_(
|
||||||
@ -827,13 +833,13 @@ main( int argc, char **argv )
|
|||||||
{
|
{
|
||||||
add_to_strlist(&unsafe_files,configname);
|
add_to_strlist(&unsafe_files,configname);
|
||||||
|
|
||||||
/* If any options file is unsafe, then disable the keyserver
|
/* If any options file is unsafe, then disable any external
|
||||||
code. Since the keyserver code can call an external
|
programs for keyserver calls or photo IDs. Since the
|
||||||
program, and the external program to call is set in the
|
external program to call is set in the options file, a
|
||||||
options file, a unsafe options file can lead to an
|
unsafe options file can lead to an arbitrary program
|
||||||
arbitrary program being run. */
|
being run. */
|
||||||
|
|
||||||
opt.keyserver_disable=1;
|
opt.exec_disable=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
configlineno = 0;
|
configlineno = 0;
|
||||||
@ -1069,6 +1075,9 @@ main( int argc, char **argv )
|
|||||||
case oComment: opt.comment_string = pargs.r.ret_str; break;
|
case oComment: opt.comment_string = pargs.r.ret_str; break;
|
||||||
case oDefaultComment: opt.comment_string = NULL; break;
|
case oDefaultComment: opt.comment_string = NULL; break;
|
||||||
case oThrowKeyid: opt.throw_keyid = 1; 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 oForceV3Sigs: opt.force_v3_sigs = 1; break;
|
||||||
case oNoForceV3Sigs: opt.force_v3_sigs = 0; break;
|
case oNoForceV3Sigs: opt.force_v3_sigs = 0; break;
|
||||||
case oForceV4Certs: opt.force_v4_certs = 1; break;
|
case oForceV4Certs: opt.force_v4_certs = 1; break;
|
||||||
|
18
g10/gpgv.c
18
g10/gpgv.c
@ -301,8 +301,10 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Stub: no decrypting, so no IDEA needed */
|
/* Stub: no decrypting, so no IDEA needed */
|
||||||
void
|
void idea_cipher_warn( int show ) {}
|
||||||
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 */
|
/* Stubs to void linking to ../cipher/cipher.c */
|
||||||
int string_to_cipher_algo( const char *string ) { return 0; }
|
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 make_dotlock( DOTLOCK h, long timeout ) { return 0;}
|
||||||
int release_dotlock( DOTLOCK h ) {return 0;}
|
int release_dotlock( DOTLOCK h ) {return 0;}
|
||||||
void remove_lockfiles(void) {}
|
void remove_lockfiles(void) {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
106
g10/keyedit.c
106
g10/keyedit.c
@ -32,6 +32,7 @@
|
|||||||
#include "iobuf.h"
|
#include "iobuf.h"
|
||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "photoid.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "trustdb.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,
|
static void show_key_with_all_names( KBNODE keyblock,
|
||||||
int only_marked, int with_fpr, int with_subkeys, int with_prefs );
|
int only_marked, int with_fpr, int with_subkeys, int with_prefs );
|
||||||
static void show_key_and_fingerprint( KBNODE keyblock );
|
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 void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||||||
static int menu_delsig( KBNODE pub_keyblock );
|
static int menu_delsig( KBNODE pub_keyblock );
|
||||||
static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_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_revsig( KBNODE keyblock );
|
||||||
static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||||||
static int enable_disable_key( KBNODE keyblock, int disable );
|
static int enable_disable_key( KBNODE keyblock, int disable );
|
||||||
|
static void menu_showphoto( KBNODE keyblock );
|
||||||
|
|
||||||
#define CONTROL_D ('D' - 'A' + 1)
|
#define CONTROL_D ('D' - 'A' + 1)
|
||||||
|
|
||||||
@ -749,10 +751,10 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
|
|||||||
enum cmdids { cmdNONE = 0,
|
enum cmdids { cmdNONE = 0,
|
||||||
cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
|
cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
|
||||||
cmdLSIGN, cmdNRSIGN, cmdREVSIG, cmdREVKEY, cmdDELSIG, cmdPRIMARY,
|
cmdLSIGN, cmdNRSIGN, cmdREVSIG, cmdREVKEY, cmdDELSIG, cmdPRIMARY,
|
||||||
cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
|
cmdDEBUG, cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY,
|
||||||
cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE,
|
cmdDELKEY, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
|
||||||
cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF,
|
cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF,
|
||||||
cmdINVCMD, cmdNOP };
|
cmdUPDPREF, cmdINVCMD, cmdSHOWPHOTO, cmdNOP };
|
||||||
static struct { const char *name;
|
static struct { const char *name;
|
||||||
enum cmdids id;
|
enum cmdids id;
|
||||||
int need_sk;
|
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_("nrsign") , cmdNRSIGN , 0,1,1, N_("sign the key non-revocably") },
|
||||||
{ N_("debug") , cmdDEBUG , 0,0,0, NULL },
|
{ N_("debug") , cmdDEBUG , 0,0,0, NULL },
|
||||||
{ N_("adduid") , cmdADDUID , 1,1,0, N_("add a user ID") },
|
{ 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") },
|
{ 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_("addkey") , cmdADDKEY , 1,1,0, N_("add a secondary key") },
|
||||||
{ N_("delkey") , cmdDELKEY , 0,1,0, N_("delete a secondary key") },
|
{ N_("delkey") , cmdDELKEY , 0,1,0, N_("delete a secondary key") },
|
||||||
{ N_("delsig") , cmdDELSIG , 0,1,0, N_("delete signatures") },
|
{ 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_("revkey") , cmdREVKEY , 1,1,0, N_("revoke a secondary key") },
|
||||||
{ N_("disable") , cmdDISABLEKEY, 0,1,0, N_("disable a key") },
|
{ N_("disable") , cmdDISABLEKEY, 0,1,0, N_("disable a key") },
|
||||||
{ N_("enable") , cmdENABLEKEY , 0,1,0, N_("enable a key") },
|
{ N_("enable") , cmdENABLEKEY , 0,1,0, N_("enable a key") },
|
||||||
|
{ N_("showphoto"),cmdSHOWPHOTO , 0,0,0, N_("show photo ID") },
|
||||||
|
|
||||||
{ NULL, cmdNONE } };
|
{ NULL, cmdNONE } };
|
||||||
enum cmdids cmd = 0;
|
enum cmdids cmd = 0;
|
||||||
@ -876,7 +882,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
|
|||||||
toggle = 0;
|
toggle = 0;
|
||||||
cur_keyblock = keyblock;
|
cur_keyblock = keyblock;
|
||||||
for(;;) { /* main loop */
|
for(;;) { /* main loop */
|
||||||
int i, arg_number;
|
int i, arg_number, photo;
|
||||||
const char *arg_string = "";
|
const char *arg_string = "";
|
||||||
char *p;
|
char *p;
|
||||||
PKT_public_key *pk=keyblock->pkt->pkt.public_key;
|
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);
|
trim_spaces(answer);
|
||||||
} while( *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 )
|
if( !*answer )
|
||||||
cmd = cmdLIST;
|
cmd = cmdLIST;
|
||||||
else if( *answer == CONTROL_D )
|
else if( *answer == CONTROL_D )
|
||||||
@ -1021,8 +1028,12 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
|
|||||||
redisplay = 1;
|
redisplay = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case cmdADDPHOTO:
|
||||||
|
photo=1;
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
case cmdADDUID:
|
case cmdADDUID:
|
||||||
if( menu_adduid( keyblock, sec_keyblock ) ) {
|
if( menu_adduid( keyblock, sec_keyblock, photo ) ) {
|
||||||
redisplay = 1;
|
redisplay = 1;
|
||||||
sec_modified = modified = 1;
|
sec_modified = modified = 1;
|
||||||
merge_keys_and_selfsig( sec_keyblock );
|
merge_keys_and_selfsig( sec_keyblock );
|
||||||
@ -1199,6 +1210,10 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case cmdSHOWPHOTO:
|
||||||
|
menu_showphoto(keyblock);
|
||||||
|
break;
|
||||||
|
|
||||||
case cmdQUIT:
|
case cmdQUIT:
|
||||||
if( have_commands )
|
if( have_commands )
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -1492,7 +1507,7 @@ show_key_and_fingerprint( KBNODE keyblock )
|
|||||||
* Return true if there is a new user id
|
* Return true if there is a new user id
|
||||||
*/
|
*/
|
||||||
static int
|
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_user_id *uid;
|
||||||
PKT_public_key *pk=NULL;
|
PKT_public_key *pk=NULL;
|
||||||
@ -1503,10 +1518,6 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock )
|
|||||||
KBNODE pub_where=NULL, sec_where=NULL;
|
KBNODE pub_where=NULL, sec_where=NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
uid = generate_user_id();
|
|
||||||
if( !uid )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
|
for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
|
||||||
if( node->pkt->pkttype == PKT_PUBLIC_KEY )
|
if( node->pkt->pkttype == PKT_PUBLIC_KEY )
|
||||||
pk = node->pkt->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 */
|
if( !node ) /* no subkey */
|
||||||
sec_where = NULL;
|
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,
|
rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0,
|
||||||
keygen_add_std_prefs, pk );
|
keygen_add_std_prefs, pk );
|
||||||
@ -1856,8 +1889,6 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
change_primary_uid_cb ( PKT_signature *sig, void *opaque )
|
change_primary_uid_cb ( PKT_signature *sig, void *opaque )
|
||||||
{
|
{
|
||||||
@ -2452,3 +2483,46 @@ enable_disable_key( KBNODE keyblock, int disable )
|
|||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "photoid.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "ttyio.h"
|
#include "ttyio.h"
|
||||||
#include "trustdb.h"
|
#include "trustdb.h"
|
||||||
@ -352,6 +353,10 @@ list_keyblock_print ( KBNODE keyblock, int secret )
|
|||||||
print_key_data( pk, keyid );
|
print_key_data( pk, keyid );
|
||||||
any = 1;
|
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 ) {
|
else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
|
||||||
u32 keyid2[2];
|
u32 keyid2[2];
|
||||||
@ -576,10 +581,10 @@ list_keyblock_colon( KBNODE keyblock, int secret )
|
|||||||
byte namehash[20];
|
byte namehash[20];
|
||||||
|
|
||||||
if( pk && !ulti_hack ) {
|
if( pk && !ulti_hack ) {
|
||||||
if( node->pkt->pkt.user_id->photo )
|
if( node->pkt->pkt.user_id->attrib_data )
|
||||||
rmd160_hash_buffer( namehash,
|
rmd160_hash_buffer( namehash,
|
||||||
node->pkt->pkt.user_id->photo,
|
node->pkt->pkt.user_id->attrib_data,
|
||||||
node->pkt->pkt.user_id->photolen);
|
node->pkt->pkt.user_id->attrib_len);
|
||||||
else
|
else
|
||||||
rmd160_hash_buffer( namehash,
|
rmd160_hash_buffer( namehash,
|
||||||
node->pkt->pkt.user_id->name,
|
node->pkt->pkt.user_id->name,
|
||||||
|
310
g10/keyserver.c
310
g10/keyserver.c
@ -34,21 +34,13 @@
|
|||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "cipher.h"
|
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
|
#include "exec.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "hkp.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 KEYSERVER_PROTO_VERSION 0
|
||||||
|
|
||||||
#define GET 0
|
#define GET 0
|
||||||
@ -74,7 +66,7 @@ parse_keyserver_options(char *options)
|
|||||||
opt.keyserver_options.include_disabled=1;
|
opt.keyserver_options.include_disabled=1;
|
||||||
else if(strcasecmp(tok,"no-include-disabled")==0)
|
else if(strcasecmp(tok,"no-include-disabled")==0)
|
||||||
opt.keyserver_options.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 ||
|
else if(strcasecmp(tok,"use-temp-files")==0 ||
|
||||||
strcasecmp(tok,"no-use-temp-files")==0)
|
strcasecmp(tok,"no-use-temp-files")==0)
|
||||||
log_info(_("Warning: keyserver option \"%s\" is not used "
|
log_info(_("Warning: keyserver option \"%s\" is not used "
|
||||||
@ -261,167 +253,75 @@ print_keyinfo(int count,char *keystring,u32 *keyid)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\""
|
||||||
|
#define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\""
|
||||||
|
|
||||||
static int
|
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};
|
int ret=0,i,gotversion=0;
|
||||||
pid_t child=0;
|
|
||||||
STRLIST temp;
|
STRLIST temp;
|
||||||
unsigned int maxlen=256,buflen;
|
unsigned int maxlen=256,buflen;
|
||||||
char *filename=NULL,*tempfile_in=NULL,*tempfile_out=NULL,*searchstr=NULL;
|
char *command=NULL,*searchstr=NULL;
|
||||||
char *tempdir=NULL;
|
|
||||||
byte *line=NULL;
|
byte *line=NULL;
|
||||||
FILE *tochild=NULL;
|
struct exec_info *spawn;
|
||||||
IOBUF fromchild=NULL;
|
|
||||||
int gotversion=0,madedir=0;
|
|
||||||
|
|
||||||
#ifndef __MINGW32__
|
#ifdef EXEC_TEMPFILE_ONLY
|
||||||
/* Don't allow to be setuid when we are going to create temporary
|
opt.keyserver_options.use_temp_files=1;
|
||||||
files or directories - yes, this is a bit paranoid */
|
|
||||||
if (getuid() != geteuid() )
|
|
||||||
BUG ();
|
|
||||||
#endif
|
#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 */
|
/* Build the filename for the helper to execute */
|
||||||
|
|
||||||
filename=m_alloc(strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1);
|
command=m_alloc(strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1);
|
||||||
|
strcpy(command,"gpgkeys_");
|
||||||
|
strcat(command,opt.keyserver_scheme);
|
||||||
strcpy(filename,"gpgkeys_");
|
|
||||||
strcat(filename,opt.keyserver_scheme);
|
|
||||||
|
|
||||||
if(opt.keyserver_options.use_temp_files)
|
if(opt.keyserver_options.use_temp_files)
|
||||||
{
|
{
|
||||||
const char *tmp=get_temp_dir();
|
if(opt.keyserver_options.keep_temp_files)
|
||||||
|
|
||||||
tempdir=m_alloc(strlen(tmp)+1+10+1);
|
|
||||||
sprintf(tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp);
|
|
||||||
|
|
||||||
if(mkdtemp(tempdir)==NULL)
|
|
||||||
{
|
{
|
||||||
log_error(_("%s: can't create temp directory: %s\n"),
|
command=m_realloc(command,strlen(command)+
|
||||||
tempdir,strerror(errno));
|
strlen(KEYSERVER_ARGS_KEEP)+1);
|
||||||
goto fail;
|
strcat(command,KEYSERVER_ARGS_KEEP);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
command=m_realloc(command,strlen(command)+
|
||||||
|
strlen(KEYSERVER_ARGS_NOKEEP)+1);
|
||||||
|
strcat(command,KEYSERVER_ARGS_NOKEEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
madedir=1;
|
ret=exec_write(&spawn,NULL,command,0,0);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
ret=exec_write(&spawn,command,NULL,0,0);
|
||||||
if(pipe(to)==-1)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if(pipe(from)==-1)
|
if(ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if((child=fork())==-1)
|
fprintf(spawn->tochild,"# This is a gpg keyserver communications file\n");
|
||||||
goto fail;
|
fprintf(spawn->tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
|
||||||
|
fprintf(spawn->tochild,"PROGRAM %s\n",VERSION);
|
||||||
if(child==0)
|
fprintf(spawn->tochild,"HOST %s\n",opt.keyserver_host);
|
||||||
{
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
if(atoi(opt.keyserver_port)>0)
|
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 */
|
/* Write options */
|
||||||
|
|
||||||
fprintf(tochild,"OPTION %sinclude-revoked\n",
|
fprintf(spawn->tochild,"OPTION %sinclude-revoked\n",
|
||||||
opt.keyserver_options.include_revoked?"":"no-");
|
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-");
|
opt.keyserver_options.include_disabled?"":"no-");
|
||||||
|
|
||||||
for(i=0;i<opt.keyserver_options.verbose;i++)
|
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;
|
temp=opt.keyserver_options.other;
|
||||||
|
|
||||||
for(;temp;temp=temp->next)
|
for(;temp;temp=temp->next)
|
||||||
fprintf(tochild,"OPTION %s\n",temp->d);
|
fprintf(spawn->tochild,"OPTION %s\n",temp->d);
|
||||||
|
|
||||||
switch(action)
|
switch(action)
|
||||||
{
|
{
|
||||||
@ -429,15 +329,15 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fprintf(tochild,"COMMAND GET\n\n");
|
fprintf(spawn->tochild,"COMMAND GET\n\n");
|
||||||
|
|
||||||
/* Which keys do we want? */
|
/* Which keys do we want? */
|
||||||
|
|
||||||
for(i=0;i<count;i++)
|
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]);
|
(ulong)kidlist[i][0],(ulong)kidlist[i][1]);
|
||||||
|
|
||||||
fprintf(tochild,"\n");
|
fprintf(spawn->tochild,"\n");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -447,7 +347,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
|
|||||||
STRLIST key,temp;
|
STRLIST key,temp;
|
||||||
|
|
||||||
/* Note the extra \n here to send an empty keylist block */
|
/* 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)
|
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);
|
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),
|
fwrite(iobuf_get_temp_buffer(buffer),
|
||||||
iobuf_get_temp_length(buffer),1,tochild);
|
iobuf_get_temp_length(buffer),1,spawn->tochild);
|
||||||
fprintf(tochild,"KEY %s END\n",key->d);
|
fprintf(spawn->tochild,"KEY %s END\n",key->d);
|
||||||
|
|
||||||
iobuf_close(buffer);
|
iobuf_close(buffer);
|
||||||
}
|
}
|
||||||
@ -485,14 +385,14 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
|
|||||||
{
|
{
|
||||||
STRLIST key;
|
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
|
/* Which keys do we want? Remember that the gpgkeys_ program
|
||||||
is going to lump these together into a search string. */
|
is going to lump these together into a search string. */
|
||||||
|
|
||||||
for(key=list;key!=NULL;key=key->next)
|
for(key=list;key!=NULL;key=key->next)
|
||||||
{
|
{
|
||||||
fprintf(tochild,"%s\n",key->d);
|
fprintf(spawn->tochild,"%s\n",key->d);
|
||||||
if(key!=list)
|
if(key!=list)
|
||||||
{
|
{
|
||||||
searchstr=m_realloc(searchstr,
|
searchstr=m_realloc(searchstr,
|
||||||
@ -508,7 +408,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
|
|||||||
strcat(searchstr,key->d);
|
strcat(searchstr,key->d);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(tochild,"\n");
|
fprintf(spawn->tochild,"\n");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -518,52 +418,16 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Done sending */
|
/* Done sending, so start reading. */
|
||||||
fclose(tochild);
|
ret=exec_read(spawn);
|
||||||
tochild=NULL;
|
if(ret)
|
||||||
to[1]=-1;
|
goto fail;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now handle the response */
|
/* Now handle the response */
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if(iobuf_read_line(fromchild,&line,&buflen,&maxlen)==0)
|
if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0)
|
||||||
{
|
{
|
||||||
ret=G10ERR_READ_FILE;
|
ret=G10ERR_READ_FILE;
|
||||||
goto fail; /* i.e. EOF */
|
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
|
do this could be to continue parsing this line-by-line and
|
||||||
make a temp iobuf for each key. */
|
make a temp iobuf for each key. */
|
||||||
|
|
||||||
import_keys_stream(fromchild,
|
import_keys_stream(spawn->fromchild,
|
||||||
opt.keyserver_options.fast_import,stats_handle);
|
opt.keyserver_options.fast_import,stats_handle);
|
||||||
|
|
||||||
import_print_stats(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 */
|
/* Look for the COUNT line */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if(iobuf_read_line(fromchild,&line,&buflen,&maxlen)==0)
|
if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0)
|
||||||
{
|
{
|
||||||
ret=G10ERR_READ_FILE;
|
ret=G10ERR_READ_FILE;
|
||||||
goto fail; /* i.e. EOF */
|
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);
|
while(sscanf(line,"COUNT %d\n",&count)!=1);
|
||||||
|
|
||||||
keyserver_search_prompt(fromchild,count,searchstr);
|
keyserver_search_prompt(spawn->fromchild,count,searchstr);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -652,54 +516,9 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
iobuf_close(fromchild);
|
*prog=exec_finish(spawn);
|
||||||
fromchild=NULL;
|
|
||||||
ret=0;
|
|
||||||
|
|
||||||
fail:
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -707,11 +526,7 @@ keyserver_spawn(int action,STRLIST list,u32 (*kidlist)[2],int count)
|
|||||||
static int
|
static int
|
||||||
keyserver_work(int action,STRLIST list,u32 (*kidlist)[2],int count)
|
keyserver_work(int action,STRLIST list,u32 (*kidlist)[2],int count)
|
||||||
{
|
{
|
||||||
int rc=0;
|
int rc=0,ret=0;
|
||||||
|
|
||||||
#ifdef KEYSERVER_TEMPFILE_ONLY
|
|
||||||
opt.keyserver_options.use_temp_files=1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(opt.keyserver_scheme==NULL ||
|
if(opt.keyserver_scheme==NULL ||
|
||||||
opt.keyserver_host==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 */
|
/* 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:
|
case KEYSERVER_SCHEME_NOT_FOUND:
|
||||||
log_error(_("no handler for keyserver scheme \"%s\"\n"),
|
log_error(_("no handler for keyserver scheme \"%s\"\n"),
|
||||||
opt.keyserver_scheme);
|
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 */
|
/* This is not the best error code for this */
|
||||||
return G10ERR_INVALID_URI;
|
return G10ERR_INVALID_URI;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_error(_("keyserver communications error\n"));
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,8 @@ struct {
|
|||||||
const char *set_filename;
|
const char *set_filename;
|
||||||
const char *comment_string;
|
const char *comment_string;
|
||||||
int throw_keyid;
|
int throw_keyid;
|
||||||
|
int show_photos;
|
||||||
|
const char *photo_viewer;
|
||||||
int s2k_mode;
|
int s2k_mode;
|
||||||
int s2k_digest_algo;
|
int s2k_digest_algo;
|
||||||
int s2k_cipher_algo;
|
int s2k_cipher_algo;
|
||||||
@ -104,7 +106,7 @@ struct {
|
|||||||
int keep_temp_files:1;
|
int keep_temp_files:1;
|
||||||
STRLIST other;
|
STRLIST other;
|
||||||
} keyserver_options;
|
} keyserver_options;
|
||||||
int keyserver_disable;
|
int exec_disable;
|
||||||
int no_perm_warn;
|
int no_perm_warn;
|
||||||
char *temp_dir;
|
char *temp_dir;
|
||||||
int no_encrypt_to;
|
int no_encrypt_to;
|
||||||
|
@ -115,7 +115,7 @@ lock-once
|
|||||||
# proxies (honor-http-proxy)
|
# proxies (honor-http-proxy)
|
||||||
#
|
#
|
||||||
# Most users just set the name and type of their preferred keyserver.
|
# 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.
|
# give you a quasi-random server each time.
|
||||||
|
|
||||||
#keyserver mailto:pgp-public-keys@keys.nl.pgp.net
|
#keyserver mailto:pgp-public-keys@keys.nl.pgp.net
|
||||||
@ -151,7 +151,32 @@ lock-once
|
|||||||
|
|
||||||
#auto-key-retrieve
|
#auto-key-retrieve
|
||||||
|
|
||||||
# The environment variable http_proxy is only used when the
|
# Uncomment this line to display photo user IDs in key listings
|
||||||
# this option is set.
|
#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"
|
||||||
|
28
g10/packet.h
28
g10/packet.h
@ -46,7 +46,7 @@ typedef enum {
|
|||||||
PKT_USER_ID =13, /* user id packet */
|
PKT_USER_ID =13, /* user id packet */
|
||||||
PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */
|
PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */
|
||||||
PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */
|
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_ENCRYPTED_MDC =18, /* integrity protected encrypted data */
|
||||||
PKT_MDC =19, /* manipulaion detection code packet */
|
PKT_MDC =19, /* manipulaion detection code packet */
|
||||||
PKT_COMMENT =61, /* new comment packet (private) */
|
PKT_COMMENT =61, /* new comment packet (private) */
|
||||||
@ -140,12 +140,26 @@ typedef struct {
|
|||||||
MPI data[PUBKEY_MAX_NSIG];
|
MPI data[PUBKEY_MAX_NSIG];
|
||||||
} PKT_signature;
|
} 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 {
|
typedef struct {
|
||||||
int ref; /* reference counter */
|
int ref; /* reference counter */
|
||||||
int len; /* length of the name */
|
int len; /* length of the name */
|
||||||
char *photo; /* if this is not NULL, the packet is a photo ID */
|
struct user_attribute *attribs;
|
||||||
int photolen; /* and the length of the photo */
|
int numattribs;
|
||||||
|
byte *attrib_data; /* if this is not NULL, the packet is an attribute */
|
||||||
|
unsigned long attrib_len;
|
||||||
int help_key_usage;
|
int help_key_usage;
|
||||||
u32 help_key_expire;
|
u32 help_key_expire;
|
||||||
int is_primary;
|
int is_primary;
|
||||||
@ -367,6 +381,8 @@ const byte *parse_sig_subpkt ( const subpktarea_t *buffer,
|
|||||||
const byte *parse_sig_subpkt2 ( PKT_signature *sig,
|
const byte *parse_sig_subpkt2 ( PKT_signature *sig,
|
||||||
sigsubpkttype_t reqtype,
|
sigsubpkttype_t reqtype,
|
||||||
size_t *ret_n );
|
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,
|
PACKET *create_gpg_control ( ctrlpkttype_t type,
|
||||||
const byte *data,
|
const byte *data,
|
||||||
size_t datalen );
|
size_t datalen );
|
||||||
@ -379,6 +395,9 @@ void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
|
|||||||
const byte *buffer, size_t buflen );
|
const byte *buffer, size_t buflen );
|
||||||
void build_sig_subpkt_from_sig( PKT_signature *sig );
|
void build_sig_subpkt_from_sig( PKT_signature *sig );
|
||||||
int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type );
|
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 --*/
|
/*-- free-packet.c --*/
|
||||||
void free_symkey_enc( PKT_symkey_enc *enc );
|
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 free_public_key( PKT_public_key *key );
|
||||||
void release_secret_key_parts( PKT_secret_key *sk );
|
void release_secret_key_parts( PKT_secret_key *sk );
|
||||||
void free_secret_key( 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_user_id( PKT_user_id *uid );
|
||||||
void free_comment( PKT_comment *rem );
|
void free_comment( PKT_comment *rem );
|
||||||
void free_packet( PACKET *pkt );
|
void free_packet( PACKET *pkt );
|
||||||
|
@ -61,7 +61,7 @@ static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
|
|||||||
byte *hdr, int hdrlen, PACKET *packet );
|
byte *hdr, int hdrlen, PACKET *packet );
|
||||||
static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
|
static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||||
PACKET *packet );
|
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 );
|
PACKET *packet );
|
||||||
static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
|
static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||||
PACKET *packet );
|
PACKET *packet );
|
||||||
@ -438,9 +438,9 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
|
|||||||
case PKT_USER_ID:
|
case PKT_USER_ID:
|
||||||
rc = parse_user_id(inp, pkttype, pktlen, pkt );
|
rc = parse_user_id(inp, pkttype, pktlen, pkt );
|
||||||
break;
|
break;
|
||||||
case PKT_PHOTO_ID:
|
case PKT_ATTRIBUTE:
|
||||||
pkt->pkttype = pkttype = PKT_USER_ID; /* we store it in the userID */
|
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;
|
break;
|
||||||
case PKT_OLD_COMMENT:
|
case PKT_OLD_COMMENT:
|
||||||
case PKT_COMMENT:
|
case PKT_COMMENT:
|
||||||
@ -1657,6 +1657,98 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
|
|||||||
return rc;
|
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
|
static int
|
||||||
parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
|
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;
|
byte *p;
|
||||||
|
|
||||||
packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + pktlen);
|
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->len = pktlen;
|
||||||
packet->pkt.user_id->photo = NULL;
|
|
||||||
packet->pkt.user_id->photolen = 0;
|
setup_user_id(packet);
|
||||||
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;
|
|
||||||
|
|
||||||
p = packet->pkt.user_id->name;
|
p = packet->pkt.user_id->name;
|
||||||
for( ; pktlen; pktlen--, p++ )
|
for( ; pktlen; pktlen--, p++ )
|
||||||
@ -1695,35 +1780,45 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
|
|||||||
return 0;
|
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
|
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;
|
byte *p;
|
||||||
|
|
||||||
packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + 30);
|
packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + 50);
|
||||||
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);
|
setup_user_id(packet);
|
||||||
packet->pkt.user_id->photolen = pktlen;
|
|
||||||
p = packet->pkt.user_id->photo;
|
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++ )
|
for( ; pktlen; pktlen--, p++ )
|
||||||
*p = iobuf_get_noeof(inp);
|
*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 ) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -323,17 +323,17 @@ hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig )
|
|||||||
PKT_user_id *uid = unode->pkt->pkt.user_id;
|
PKT_user_id *uid = unode->pkt->pkt.user_id;
|
||||||
|
|
||||||
assert( unode->pkt->pkttype == PKT_USER_ID );
|
assert( unode->pkt->pkttype == PKT_USER_ID );
|
||||||
if( uid->photo ) {
|
if( uid->attrib_data ) {
|
||||||
if( sig->version >=4 ) {
|
if( sig->version >=4 ) {
|
||||||
byte buf[5];
|
byte buf[5];
|
||||||
buf[0] = 0xd1; /* packet of type 17 */
|
buf[0] = 0xd1; /* packet of type 17 */
|
||||||
buf[1] = uid->photolen >> 24; /* always use 4 length bytes */
|
buf[1] = uid->attrib_len >> 24; /* always use 4 length bytes */
|
||||||
buf[2] = uid->photolen >> 16;
|
buf[2] = uid->attrib_len >> 16;
|
||||||
buf[3] = uid->photolen >> 8;
|
buf[3] = uid->attrib_len >> 8;
|
||||||
buf[4] = uid->photolen;
|
buf[4] = uid->attrib_len;
|
||||||
md_write( md, buf, 5 );
|
md_write( md, buf, 5 );
|
||||||
}
|
}
|
||||||
md_write( md, uid->photo, uid->photolen );
|
md_write( md, uid->attrib_data, uid->attrib_len );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( sig->version >=4 ) {
|
if( sig->version >=4 ) {
|
||||||
|
26
g10/sign.c
26
g10/sign.c
@ -110,14 +110,28 @@ hash_uid (MD_HANDLE md, int sigversion, const PKT_user_id *uid)
|
|||||||
{
|
{
|
||||||
if ( sigversion >= 4 ) {
|
if ( sigversion >= 4 ) {
|
||||||
byte buf[5];
|
byte buf[5];
|
||||||
buf[0] = 0xb4; /* indicates a userid packet */
|
|
||||||
buf[1] = uid->len >> 24; /* always use 4 length bytes */
|
if(uid->attrib_data) {
|
||||||
buf[2] = uid->len >> 16;
|
buf[0] = 0xd1; /* indicates an attribute packet */
|
||||||
buf[3] = uid->len >> 8;
|
buf[1] = uid->attrib_len >> 24; /* always use 4 length bytes */
|
||||||
buf[4] = uid->len;
|
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, 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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -951,8 +951,8 @@ store_validation_status (int depth, KBNODE keyblock)
|
|||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
{
|
{
|
||||||
if( uid->photo )
|
if( uid->attrib_data )
|
||||||
rmd160_hash_buffer (namehash, uid->photo, uid->photolen);
|
rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len);
|
||||||
else
|
else
|
||||||
rmd160_hash_buffer (namehash, uid->name, uid->len );
|
rmd160_hash_buffer (namehash, uid->name, uid->len );
|
||||||
|
|
||||||
@ -1373,8 +1373,8 @@ validate_keys (int interactive)
|
|||||||
byte namehash[20];
|
byte namehash[20];
|
||||||
PKT_user_id *uid = node->pkt->pkt.user_id;
|
PKT_user_id *uid = node->pkt->pkt.user_id;
|
||||||
|
|
||||||
if( uid->photo )
|
if( uid->attrib_data )
|
||||||
rmd160_hash_buffer (namehash, uid->photo, uid->photolen);
|
rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len);
|
||||||
else
|
else
|
||||||
rmd160_hash_buffer (namehash, uid->name, uid->len );
|
rmd160_hash_buffer (namehash, uid->name, uid->len );
|
||||||
update_validity (pk, namehash, 0, TRUST_ULTIMATE);
|
update_validity (pk, namehash, 0, TRUST_ULTIMATE);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user