From 4fea8fdbbb79144cef5c9a34a0c3a4bb4a649bc1 Mon Sep 17 00:00:00 2001 From: David Shaw Date: Wed, 8 Mar 2006 23:30:12 +0000 Subject: [PATCH] * options.h, sign.c (mk_notation_policy_etc), gpg.c (add_notation_data): Use it here for the various notation commands. * packet.h, main.h, keygen.c (keygen_add_notations), build-packet.c (string_to_notation, sig_to_notation) (free_notation): New "one stop shopping" functions to handle notations and start removing some code duplication. --- g10/ChangeLog | 11 ++++ g10/build-packet.c | 153 ++++++++++++++++++++++++++++++++++++++++++++- g10/gpg.c | 73 ++++----------------- g10/keyedit.c | 6 +- g10/keygen.c | 48 +++++++++++++- g10/main.h | 7 ++- g10/options.h | 4 +- g10/packet.h | 19 +++++- g10/sign.c | 71 +++++++++------------ 9 files changed, 275 insertions(+), 117 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 032d626a7..cdd772235 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,14 @@ +2006-03-08 David Shaw + + * options.h, sign.c (mk_notation_policy_etc), gpg.c + (add_notation_data): Use it here for the various notation + commands. + + * packet.h, main.h, keygen.c (keygen_add_notations), + build-packet.c (string_to_notation, sig_to_notation) + (free_notation): New "one stop shopping" functions to handle + notations and start removing some code duplication. + 2006-03-07 David Shaw * options.h, mainproc.c (check_sig_and_print), gpg.c (main): diff --git a/g10/build-packet.c b/g10/build-packet.c index f81ae8875..1ceac358d 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -1,6 +1,6 @@ /* build-packet.c - assemble packets and write them - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -25,6 +25,7 @@ #include #include #include +#include #include "packet.h" #include "errors.h" @@ -33,6 +34,7 @@ #include "util.h" #include "cipher.h" #include "memory.h" +#include "i18n.h" #include "options.h" static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ); @@ -886,6 +888,153 @@ build_attribute_subpkt(PKT_user_id *uid,byte type, uid->attrib_len+=idx+headerlen+buflen; } +struct notation * +string_to_notation(const char *string,int is_utf8) +{ + const char *s,*i; + int saw_at=0,highbit=0; + struct notation *notation; + + notation=xmalloc_clear(sizeof(*notation)); + + if(*string=='!') + { + notation->flags.critical=1; + string++; + } + + /* If and when the IETF assigns some official name tags, we'll have + to add them here. */ + + for( s=string ; *s != '='; s++ ) + { + if( *s=='@') + saw_at++; + + if( !*s || !isascii (*s) || (!isgraph(*s) && !isspace(*s)) ) + { + log_error(_("a notation name must have only printable characters" + " or spaces, and end with an '='\n") ); + goto fail; + } + } + + notation->name=xmalloc((s-string)+1); + strncpy(notation->name,string,s-string); + notation->name[s-string]='\0'; + + if(!saw_at && !opt.expert) + { + log_error(_("a user notation name must contain the '@' character\n")); + goto fail; + } + + if (saw_at > 1) + { + log_error(_("a notation name must not contain more than" + " one '@' character\n")); + goto fail; + } + + i=s+1; + + /* we only support printable text - therefore we enforce the use of + only printable characters (an empty value is valid) */ + for(s++; *s ; s++ ) + { + if ( !isascii (*s) ) + highbit=1; + else if (iscntrl(*s)) + { + log_error(_("a notation value must not use any" + " control characters\n")); + goto fail; + } + } + + if(!highbit || is_utf8) + notation->value=xstrdup(i); + else + notation->value=native_to_utf8(i); + + return notation; + + fail: + free_notation(notation); + return NULL; +} + +struct notation * +sig_to_notation(PKT_signature *sig) +{ + const byte *p; + size_t len; + int seq=0,crit; + struct notation *list=NULL; + + while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,&len,&seq,&crit))) + { + int n1,n2; + struct notation *n=NULL; + + if(len<8) + { + log_info(_("WARNING: invalid notation data found\n")); + continue; + } + + n1=(p[4]<<8)|p[5]; + n2=(p[6]<<8)|p[7]; + + if(8+n1+n2!=len) + { + log_info(_("WARNING: invalid notation data found\n")); + continue; + } + + n=xmalloc_clear(sizeof(*n)); + n->name=xmalloc(n1+1); + + memcpy(n->name,&p[8],n1); + n->name[n1]='\0'; + + if(p[0]&0x80) + { + n->value=xmalloc(n2+1); + memcpy(n->value,&p[8+n1],n2); + n->value[n2]='\0'; + } + else + { + n->value=xmalloc(2+strlen(_("not human readable"))+2+1); + strcpy(n->value,"[ "); + strcat(n->value,_("not human readable")); + strcat(n->value," ]"); + } + + n->flags.critical=crit; + + n->next=list; + list=n; + } + + return list; +} + +void +free_notation(struct notation *notation) +{ + while(notation) + { + struct notation *n=notation; + + xfree(n->name); + xfree(n->value); + notation=n->next; + xfree(n); + } +} + static int do_signature( IOBUF out, int ctb, PKT_signature *sig ) { diff --git a/g10/gpg.c b/g10/gpg.c index fa50fc207..532f3976e 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -3974,69 +3974,22 @@ print_mds( const char *fname, int algo ) static void add_notation_data( const char *string, int which ) { - const char *s; - STRLIST sl,*notation_data; - int critical=0; - int highbit=0; - int saw_at=0; + struct notation *notation; - if(which) - notation_data=&opt.cert_notation_data; - else - notation_data=&opt.sig_notation_data; - - if( *string == '!' ) { - critical = 1; - string++; - } - - /* If and when the IETF assigns some official name tags, we'll - have to add them here. */ - - for( s=string ; *s != '='; s++ ) - { - if( *s=='@') - saw_at++; - - if( !*s || !isascii (*s) || (!isgraph(*s) && !isspace(*s)) ) - { - log_error(_("a notation name must have only printable characters " - "or spaces, and end with an '='\n") ); - return; - } - } - - if(!saw_at && !opt.expert) - { - log_error(_("a user notation name must contain the '@' character\n")); - return; - } - if (saw_at > 1) - { - log_error(_("a notation name must not contain more than " - "one '@' character\n")); - return; - } - - /* we only support printable text - therefore we enforce the use - * of only printable characters (an empty value is valid) */ - for( s++; *s ; s++ ) { - if ( !isascii (*s) ) - highbit = 1; - else if (iscntrl(*s)) { - log_error(_("a notation value must not use" - " any control characters\n") ); - return; + notation=string_to_notation(string,utf8_strings); + if(notation) + { + if(which) + { + notation->next=opt.cert_notations; + opt.cert_notations=notation; + } + else + { + notation->next=opt.sig_notations; + opt.sig_notations=notation; } } - - if( highbit ) /* must use UTF8 encoding */ - sl = add_to_strlist2( notation_data, string, utf8_strings ); - else - sl = add_to_strlist( notation_data, string ); - - if( critical ) - sl->flags |= 1; } static void diff --git a/g10/keyedit.c b/g10/keyedit.c index d451e5079..32b57f829 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -1,6 +1,6 @@ /* keyedit.c - keyedit stuff - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -546,7 +546,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, byte trust_depth=0,trust_value=0; if(local || nonrevocable || trust || - opt.cert_policy_url || opt.cert_notation_data) + opt.cert_policy_url || opt.cert_notations) force_v4=1; /* we have to use a copy of the sk, because make_keysig_packet diff --git a/g10/keygen.c b/g10/keygen.c index 637a1b3c4..ba7616bf3 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1,6 +1,6 @@ /* keygen.c - generate a key pair - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -689,6 +689,50 @@ keygen_add_keyserver_url(PKT_signature *sig, void *opaque) return 0; } +int +keygen_add_notations(PKT_signature *sig,void *opaque) +{ + struct notation *notation; + + /* We always start clean */ + delete_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION); + delete_sig_subpkt(sig->unhashed,SIGSUBPKT_NOTATION); + sig->flags.notation=0; + + for(notation=opaque;notation;notation=notation->next) + if(!notation->flags.ignore) + { + unsigned char *buf; + unsigned int n1,n2; + + n1=strlen(notation->name); + if(notation->altvalue) + n2=strlen(notation->altvalue); + else + n2=strlen(notation->value); + + buf = xmalloc( 8 + n1 + n2 ); + + buf[0] = 0x80; /* human readable */ + buf[1] = buf[2] = buf[3] = 0; + buf[4] = n1 >> 8; + buf[5] = n1; + buf[6] = n2 >> 8; + buf[7] = n2; + memcpy(buf+8, notation->name, n1 ); + if(notation->altvalue) + memcpy(buf+8+n1, notation->altvalue, n2 ); + else + memcpy(buf+8+n1, notation->value, n2 ); + build_sig_subpkt( sig, SIGSUBPKT_NOTATION | + (notation->flags.critical?SIGSUBPKT_FLAG_CRITICAL:0), + buf, 8+n1+n2 ); + xfree(buf); + } + + return 0; +} + int keygen_add_revkey(PKT_signature *sig, void *opaque) { diff --git a/g10/main.h b/g10/main.h index a67c2ff3f..69150a301 100644 --- a/g10/main.h +++ b/g10/main.h @@ -1,6 +1,6 @@ /* main.h - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -55,7 +55,7 @@ struct groupitem struct groupitem *next; }; -/*-- g10.c --*/ +/*-- gpg.c --*/ extern int g10_errors_seen; #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) @@ -181,6 +181,7 @@ int keygen_add_key_expire( PKT_signature *sig, void *opaque ); int keygen_add_std_prefs( PKT_signature *sig, void *opaque ); int keygen_upd_std_prefs( PKT_signature *sig, void *opaque ); int keygen_add_keyserver_url(PKT_signature *sig, void *opaque); +int keygen_add_notations(PKT_signature *sig,void *opaque); int keygen_add_revkey(PKT_signature *sig, void *opaque); int make_backsig(PKT_signature *sig,PKT_public_key *pk, PKT_public_key *sub_pk,PKT_secret_key *sub_sk); diff --git a/g10/options.h b/g10/options.h index bcef4550b..6ae586eef 100644 --- a/g10/options.h +++ b/g10/options.h @@ -163,8 +163,8 @@ struct char *temp_dir; int no_encrypt_to; int interactive; - STRLIST sig_notation_data; - STRLIST cert_notation_data; + struct notation *sig_notations; + struct notation *cert_notations; STRLIST sig_policy_url; STRLIST cert_policy_url; STRLIST sig_keyserver_url; diff --git a/g10/packet.h b/g10/packet.h index 56d9f0bd8..c40f2f123 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -1,6 +1,6 @@ /* packet.h - packet definitions - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -407,6 +407,18 @@ typedef enum { SIGSUBPKT_FLAG_CRITICAL=128 } sigsubpkttype_t; +struct notation +{ + char *name; + char *value; + char *altvalue; + struct + { + unsigned int critical:1; + unsigned int ignore:1; + } flags; + struct notation *next; +}; /*-- mainproc.c --*/ int proc_packets( void *ctx, IOBUF a ); @@ -476,6 +488,9 @@ int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type ); void build_attribute_subpkt(PKT_user_id *uid,byte type, const void *buf,u32 buflen, const void *header,u32 headerlen); +struct notation *string_to_notation(const char *string,int is_utf8); +struct notation *sig_to_notation(PKT_signature *sig); +void free_notation(struct notation *notation); /*-- free-packet.c --*/ void free_symkey_enc( PKT_symkey_enc *enc ); diff --git a/g10/sign.c b/g10/sign.c index 24c37c10f..79e756753 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -1,6 +1,6 @@ /* sign.c - sign data - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -55,9 +55,9 @@ void __stdcall Sleep(ulong); static int recipient_digest_algo=0; /**************** - * Create a notation. It is assumed that the stings in STRLIST - * are already checked to contain only printable data and have a valid - * NAME=VALUE format. + * Create notations and other stuff. It is assumed that the stings in + * STRLIST are already checked to contain only printable data and have + * a valid NAME=VALUE format. */ static void mk_notation_policy_etc( PKT_signature *sig, @@ -65,9 +65,8 @@ mk_notation_policy_etc( PKT_signature *sig, { const char *string; char *s=NULL; - byte *buf; - unsigned n1, n2; - STRLIST nd=NULL,pu=NULL; + STRLIST pu=NULL; + struct notation *nd=NULL; struct expando_args args; memset(&args,0,sizeof(args)); @@ -80,57 +79,43 @@ mk_notation_policy_etc( PKT_signature *sig, good to do these checks anyway. */ /* notation data */ - if(IS_SIG(sig) && opt.sig_notation_data) + if(IS_SIG(sig) && opt.sig_notations) { if(sig->version<4) log_error(_("can't put notation data into v3 (PGP 2.x style) " "signatures\n")); else - nd=opt.sig_notation_data; + nd=opt.sig_notations; } - else if( IS_CERT(sig) && opt.cert_notation_data ) + else if( IS_CERT(sig) && opt.cert_notations ) { if(sig->version<4) log_error(_("can't put notation data into v3 (PGP 2.x style) " "key signatures\n")); else - nd=opt.cert_notation_data; + nd=opt.cert_notations; } - for( ; nd; nd = nd->next ) { - char *expanded; + if(nd) + { + struct notation *i; - string = nd->d; - s = strchr( string, '=' ); - if( !s ) - BUG(); /* we have already parsed this */ - n1 = s - string; - s++; - - expanded=pct_expando(s,&args); - if(!expanded) + for(i=nd;i;i=i->next) { - log_error(_("WARNING: unable to %%-expand notation " - "(too large). Using unexpanded.\n")); - expanded=xstrdup(s); + i->altvalue=pct_expando(i->value,&args); + if(!i->altvalue) + log_error(_("WARNING: unable to %%-expand notation " + "(too large). Using unexpanded.\n")); } - n2 = strlen(expanded); - buf = xmalloc( 8 + n1 + n2 ); - buf[0] = 0x80; /* human readable */ - buf[1] = buf[2] = buf[3] = 0; - buf[4] = n1 >> 8; - buf[5] = n1; - buf[6] = n2 >> 8; - buf[7] = n2; - memcpy(buf+8, string, n1 ); - memcpy(buf+8+n1, expanded, n2 ); - build_sig_subpkt( sig, SIGSUBPKT_NOTATION - | ((nd->flags & 1)? SIGSUBPKT_FLAG_CRITICAL:0), - buf, 8+n1+n2 ); - xfree(expanded); - xfree(buf); - } + keygen_add_notations(sig,nd); + + for(i=nd;i;i=i->next) + { + xfree(i->altvalue); + i->altvalue=NULL; + } + } /* set policy URL */ if( IS_SIG(sig) && opt.sig_policy_url ) @@ -650,7 +635,7 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash, if(opt.force_v3_sigs || RFC1991) sig->version=3; else if(duration || opt.sig_policy_url - || opt.sig_notation_data || opt.sig_keyserver_url) + || opt.sig_notations || opt.sig_keyserver_url) sig->version=4; else sig->version=sk->version;