1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-02-01 16:33:02 +01:00

"sigclass" patch - adds key signature class levels, notation and policy-url

displays in key listings, and shows flags for signature features.
This commit is contained in:
David Shaw 2001-12-06 22:04:08 +00:00
parent 934ac0bd7d
commit 46efe28815
10 changed files with 286 additions and 22 deletions

View File

@ -1,3 +1,46 @@
2001-12-05 David Shaw <dshaw@jabberwocky.com>
* Force a V4 sig if the user has a notation or policy URL set.
2001-12-04 David Shaw <dshaw@jabberwocky.com>
* g10.c: Add options --keyserver-options, --temp-directory, and
auto-key-retrieve (the opposite of no-auto-key-retrieve).
* hkp.c (hkp_search): New function to handle searching a HKP
keyserver for a key
* hkp.c (hkp_ask_import, hkp_export): Pretty large changes to make
them communicate via the generic functions in keyserver.c
* keyserver.c: new file with generic keyserver routines for
getting keys from a keyserver, sending keys to a keyserver, and
searching for keys on a keyserver. Calls the internal HKP stuff
in hkp.c for HKP keyserver functions. Other calls are handled by
an external program which is spawned and written to and read from
via pipes. Platforms that don't have pipes use temp files.
2001-11-20 David Shaw <dshaw@jabberwocky.com>
* options.h, g10.c: New options show-notation, no-show-notation,
default-check-level, no-default-check-level, show-policy-url,
no-show-policy-url.
* packet.h, sign.c (make_keysig_packet), parse-packet.c
(parse_signature), free-packet.c (free_seckey_enc): Fill in
structures for notation, policy, sig class, exportability, etc.
* keyedit.c, keylist.c (print_and_check_one_sig,
list_keyblock_print): Show flags in signature display for cert
details (class, local, notation, policy, revocable). If selected,
show the notation and policy url.
* keyedit.c (sign_uids): Prompt for and use different key sig
classes.
* helptext.c (helptexts): Add help text to explain different
key signature classes
2001-11-26 David Shaw <dshaw@jabberwocky.com>
* trustdb.c (mark_usable_uid_certs): Fix segfault from bad

View File

@ -68,6 +68,8 @@ enum cmd_and_opt_values { aNull = 0,
oVerbose = 'v',
oCompress = 'z',
oNotation = 'N',
oShowNotation,
oNoShowNotation,
oBatch = 500,
aClearsign,
aStore,
@ -121,6 +123,8 @@ enum cmd_and_opt_values { aNull = 0,
oWithFingerprint,
oAnswerYes,
oAnswerNo,
oDefCheckLevel,
oNoDefCheckLevel,
oKeyring,
oSecretKeyring,
oDefaultKey,
@ -175,6 +179,8 @@ enum cmd_and_opt_values { aNull = 0,
oRunAsShmCP,
oSetFilename,
oSetPolicyURL,
oShowPolicyURL,
oNoShowPolicyURL,
oUseEmbeddedFilename,
oComment,
oDefaultComment,
@ -407,11 +413,17 @@ static ARGPARSE_OPTS opts[] = {
{ oSkipVerify, "skip-verify",0, "@" },
{ oCompressKeys, "compress-keys",0, "@"},
{ oCompressSigs, "compress-sigs",0, "@"},
{ oDefCheckLevel, "default-check-level", 1, "@"},
{ oNoDefCheckLevel, "no-default-check-level", 0, "@"},
{ oAlwaysTrust, "always-trust", 0, "@"},
{ oEmuChecksumBug, "emulate-checksum-bug", 0, "@"},
{ oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
{ oSetFilename, "set-filename", 2, "@" },
{ oSetPolicyURL, "set-policy-url", 2, "@" },
{ oShowPolicyURL, "show-policy-url", 0, "@" },
{ oNoShowPolicyURL, "no-show-policy-url", 0, "@" },
{ oShowNotation, "show-notation", 0, "@" },
{ oNoShowNotation, "no-show-notation", 0, "@" },
{ oComment, "comment", 2, "@" },
{ oDefaultComment, "default-comment", 0, "@" },
{ oNoVersion, "no-version", 0, "@"},
@ -924,6 +936,8 @@ main( int argc, char **argv )
break;
case oNoArmor: opt.no_armor=1; opt.armor=0; break;
case oNoDefKeyring: default_keyring = 0; break;
case oNoDefCheckLevel: opt.def_check_level=0; break;
case oDefCheckLevel: opt.def_check_level=pargs.r.ret_int; break;
case oNoGreeting: nogreeting = 1; break;
case oNoVerbose: g10_opt_verbose = 0;
opt.verbose = 0; opt.list_sigs=0; break;
@ -1007,6 +1021,8 @@ main( int argc, char **argv )
break;
case oSetFilename: opt.set_filename = pargs.r.ret_str; break;
case oSetPolicyURL: opt.set_policy_url = pargs.r.ret_str; break;
case oShowPolicyURL: opt.show_policy_url=1; break;
case oNoShowPolicyURL: opt.show_policy_url=0; break;
case oUseEmbeddedFilename: opt.use_embedded_filename = 1; break;
case oComment: opt.comment_string = pargs.r.ret_str; break;
case oDefaultComment: opt.comment_string = NULL; break;
@ -1079,6 +1095,8 @@ main( int argc, char **argv )
break;
case oTempDir: opt.temp_dir=pargs.r.ret_str; break;
case oNotation: add_notation_data( pargs.r.ret_str ); break;
case oShowNotation: opt.show_notation=1; break;
case oNoShowNotation: opt.show_notation=0; break;
case oUtf8Strings: utf8_strings = 1; break;
case oNoUtf8Strings: utf8_strings = 0; break;
case oDisableCipherAlgo:
@ -1221,6 +1239,9 @@ main( int argc, char **argv )
log_error(_("invalid S2K mode; must be 0, 1 or 3\n"));
}
if(opt.def_check_level<0 || opt.def_check_level>3)
log_error(_("invalid default-check-level; must be 0, 1, 2, or 3\n"));
if (preference_list && keygen_set_std_prefs (preference_list))
log_error(_("invalid preferences\n"));

View File

@ -152,6 +152,24 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
"Answer \"yes\" or \"no\""
)},
{ "sign_uid.class", N_(
"When you sign a user ID on a key, you should first verify that the key\n"
"belongs to the person named in the user ID. It is useful for others to\n"
"know how carefully you verified this.\n\n"
"\"0\" means you make no particular claim as to how carefully you verified the\n"
" key.\n\n"
"\"1\" means you believe the key is owned by the person who claims to own it\n"
" but you could not, or did not verify the key at all. This is useful for\n"
" a \"persona\" verification, where you sign the key of a pseudonymous user.\n\n"
"\"2\" means you did casual verification of the key. For example, this could\n"
" mean that you verified the key fingerprint and checked the user ID on the\n"
" key against a photo ID.\n\n"
"\"3\" means you did extensive verification of the key. For example, this could\n"
" mean that you verified the key fingerprint and checked the user ID on the\n"
" key against a photo ID, and also verified the email address on the key\n"
" belongs to the key owner.\n\n"
"If you don't know what the right answer is, answer \"0\"."
)},
{ "change_passwd.empty.okay", N_(
"Answer \"yes\" or \"no\""

View File

@ -122,9 +122,16 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node,
break;
}
if( sigrc != '?' || print_without_key ) {
tty_printf("%s%c %08lX %s ",
is_rev? "rev":"sig",
sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig));
tty_printf("%s%c%c %c%c%c%c%c %08lX %s ",
is_rev? "rev":"sig",sigrc,
(sig->sig_class-0x10>0 &&
sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ',
sig->flags.exportable?' ':'L',
sig->flags.revocable?' ':'R',
sig->flags.policy_url?'P':' ',
sig->flags.notation?'N':' ',
sig->flags.expired?'X':' ',
(ulong)sig->keyid[1], datestr_from_sig(sig));
if( sigrc == '%' )
tty_printf("[%s] ", g10_errstr(rc) );
else if( sigrc == '?' )
@ -140,7 +147,14 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node,
m_free(p);
}
tty_printf("\n");
if(sig->flags.policy_url && opt.show_policy_url)
show_policy_url(sig);
if(sig->flags.notation && opt.show_notation)
show_notation(sig);
}
return (sigrc == '!');
}
@ -245,13 +259,17 @@ static int
sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
{
int rc = 0;
int class=0;
SK_LIST sk_list = NULL;
SK_LIST sk_rover = NULL;
PKT_secret_key *sk = NULL;
KBNODE node, uidnode;
PKT_public_key *primary_pk=NULL;
int select_all = !count_selected_uids(keyblock);
int upd_trust = 0;
int upd_trust = 0, force_v4=0;
if(local || opt.set_policy_url || opt.notation_data)
force_v4=1;
/* build a list of all signators.
*
@ -318,23 +336,81 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
tty_printf("\n");
show_key_with_all_names( keyblock, 1, 1, 0, 0 );
tty_printf("\n");
tty_printf(_(
"Are you really sure that you want to sign this key\n"
"with your key: \""));
if(opt.batch)
class=0x10+opt.def_check_level;
else
{
char *answer;
tty_printf(_("How carefully have you verified the key you are "
"about to sign actually belongs\nto the person named "
"above? If you don't know what to answer, enter \"0\".\n"));
tty_printf("\n");
tty_printf(_(" (0) I will not answer.%s\n"),
opt.def_check_level==0?" (default)":"");
tty_printf(_(" (1) I have not checked at all.%s\n"),
opt.def_check_level==1?" (default)":"");
tty_printf(_(" (2) I have done casual checking.%s\n"),
opt.def_check_level==2?" (default)":"");
tty_printf(_(" (3) I have done very careful checking.%s\n"),
opt.def_check_level==3?" (default)":"");
tty_printf("\n");
while(class==0)
{
answer = cpr_get("sign_uid.class",_("Your selection? "));
if(answer[0]=='\0')
class=0x10+opt.def_check_level; /* Default */
else if(strcasecmp(answer,"0")==0)
class=0x10; /* Generic */
else if(strcasecmp(answer,"1")==0)
class=0x11; /* Persona */
else if(strcasecmp(answer,"2")==0)
class=0x12; /* Casual */
else if(strcasecmp(answer,"3")==0)
class=0x13; /* Positive */
else
tty_printf(_("Invalid selection.\n"));
m_free(answer);
}
}
tty_printf(_("Are you really sure that you want to sign this key\n"
"with your key: \""));
p = get_user_id( sk_keyid, &n );
tty_print_utf8_string( p, n );
m_free(p); p = NULL;
tty_printf("\"\n\n");
tty_printf("\"\n");
if( local )
tty_printf(
_("The signature will be marked as non-exportable.\n\n"));
_("\nThe signature will be marked as non-exportable.\n"));
switch(class)
{
case 0x11:
tty_printf(_("\nI have not checked this key at all.\n"));
break;
case 0x12:
tty_printf(_("\nI have checked this key casually.\n"));
break;
case 0x13:
tty_printf(_("\nI have checked this key very carefully.\n"));
break;
}
tty_printf("\n");
if( opt.batch && opt.answer_yes )
;
;
else if( !cpr_get_answer_is_yes("sign_uid.okay", _("Really sign? ")) )
continue;
/* now we can sign the user ids */
reloop: /* (must use this, because we are modifing the list) */
primary_pk = NULL;
@ -357,12 +433,12 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
* subpacket with v3 keys and the signature becomes
* exportable */
rc = make_keysig_packet( &sig, primary_pk,
node->pkt->pkt.user_id,
NULL,
sk,
0x10, 0, local?4:0,
sign_mk_attrib,
&attrib );
node->pkt->pkt.user_id,
NULL,
sk,
class, 0, force_v4?4:0,
sign_mk_attrib,
&attrib );
if( rc ) {
log_error(_("signing failed: %s\n"), g10_errstr(rc));
goto leave;

View File

@ -63,6 +63,58 @@ secret_key_list( STRLIST list )
list_one( list, 1 );
}
void
show_policy_url(PKT_signature *sig)
{
const byte *p;
int len;
p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,&len);
if(p)
{
/* This isn't UTF8 as it is a URL(?) */
printf(" %s: ",_("Signature policy"));
print_string(stdout,p,len,0);
printf("\n");
}
}
void
show_notation(PKT_signature *sig)
{
const byte *p;
int len,seq=0;
/* There may be multiple notations in the same sig. */
while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,&len,&seq)))
if(len>=8)
{
int n1,n2;
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"));
return;
}
/* This is UTF8 */
printf(" %s: ",_("Signature notation"));
print_utf8_string(stdout,p+8,n1);
printf("=");
if(*p&0x80)
print_utf8_string(stdout,p+8+n1,n2);
else
printf("[ %s ]",_("not human readable"));
printf("\n");
}
else
log_info(_("WARNING: invalid notation data found\n"));
}
static void
list_all( int secret )
@ -374,8 +426,15 @@ list_keyblock_print ( KBNODE keyblock, int secret )
sigrc = ' ';
}
fputs( sigstr, stdout );
printf("%c %08lX %s ",
sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig));
printf("%c%c %c%c%c%c%c %08lX %s ",
sigrc,(sig->sig_class-0x10>0 &&
sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ',
sig->flags.exportable?' ':'L',
sig->flags.revocable?' ':'R',
sig->flags.policy_url?'P':' ',
sig->flags.notation?'N':' ',
sig->flags.expired?'X':' ',
(ulong)sig->keyid[1], datestr_from_sig(sig));
if( sigrc == '%' )
printf("[%s] ", g10_errstr(rc) );
else if( sigrc == '?' )
@ -387,6 +446,13 @@ list_keyblock_print ( KBNODE keyblock, int secret )
m_free(p);
}
putchar('\n');
if(sig->flags.policy_url && opt.show_policy_url)
show_policy_url(sig);
if(sig->flags.notation && opt.show_notation)
show_notation(sig);
/* fixme: check or list other sigs here */
}
}

View File

@ -156,6 +156,8 @@ void release_revocation_reason_info( struct revocation_reason_info *reason );
void public_key_list( STRLIST list );
void secret_key_list( STRLIST list );
void print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode);
void show_policy_url(PKT_signature *sig);
void show_notation(PKT_signature *sig);
/*-- verify.c --*/
int verify_signatures( int nfiles, char **files );

View File

@ -65,6 +65,7 @@ struct {
const char *def_secret_key;
char *def_recipient;
int def_recipient_self;
int def_check_level;
int no_comment;
int no_version;
int marginals_needed;
@ -106,7 +107,9 @@ struct {
int no_encrypt_to;
int interactive;
STRLIST notation_data;
int show_notation;
const char *set_policy_url;
int show_policy_url;
int use_embedded_filename;
int allow_non_selfsigned_uid;
int allow_freeform_uid;

View File

@ -120,9 +120,15 @@ typedef struct {
unsigned checked:1; /* signature has been checked */
unsigned valid:1; /* signature is good (if checked is set) */
unsigned unknown_critical:1;
unsigned exportable:1;
unsigned revocable:1;
unsigned policy_url:1; /* Policy URL is present */
unsigned notation:1; /* At least one notation is present */
unsigned expired:1;
} flags;
u32 keyid[2]; /* 64 bit keyid */
u32 timestamp; /* signature made */
u32 expiredate; /* expires at this date or 0 if not at all */
byte version;
byte sig_class; /* sig classification, append for MD calculation*/
byte pubkey_algo; /* algorithm used for public key scheme */

View File

@ -910,6 +910,7 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
case SIGSUBPKT_KEY_FLAGS:
return 0;
case SIGSUBPKT_EXPORTABLE:
case SIGSUBPKT_REVOCABLE:
if( !n )
break;
return 0;
@ -974,9 +975,9 @@ can_handle_critical( const byte *buffer, size_t n, int type )
case SIGSUBPKT_KEY_FLAGS:
case SIGSUBPKT_PRIMARY_UID:
case SIGSUBPKT_FEATURES:
case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */
return 1;
case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */
default:
return 0;
}
@ -1108,7 +1109,6 @@ parse_sig_subpkt2 (PKT_signature *sig, sigsubpkttype_t reqtype,
}
static int
parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_signature *sig )
@ -1143,6 +1143,8 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
}
sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
sig->digest_algo = iobuf_get_noeof(inp); pktlen--;
sig->flags.exportable=1;
sig->flags.revocable=1;
if( is_v4 ) { /* read subpackets */
n = read_16(inp); pktlen -= 2; /* length of hashed data */
if( n > 10000 ) {
@ -1218,6 +1220,33 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
sig->keyid[0] = buffer_to_u32(p);
sig->keyid[1] = buffer_to_u32(p+4);
}
p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL);
if(p)
sig->expiredate=sig->timestamp+buffer_to_u32(p);
if(sig->expiredate>0 && sig->expiredate<make_timestamp())
sig->flags.expired=1;
p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,NULL);
if(p)
sig->flags.policy_url=1;
p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,NULL);
if(p)
sig->flags.notation=1;
p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_REVOCABLE,NULL);
if(p && *p==0)
sig->flags.revocable=0;
/* We accept this subpacket from either the hashed or unhashed
areas as older versions of gpg put it in the unhashed area.
In theory, anyway, we should never see this packet off of a
local keyring. */
p=parse_sig_subpkt2(sig,SIGSUBPKT_EXPORTABLE,NULL);
if(p && *p==0)
sig->flags.exportable=0;
}
if( list_mode ) {
@ -1992,5 +2021,3 @@ create_gpg_control( ctrlpkttype_t type, const byte *data, size_t datalen )
return packet;
}

View File

@ -1025,6 +1025,8 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
/* and make the signature packet */
sig = m_alloc_clear( sizeof *sig );
sig->version = sigversion;
sig->flags.exportable=1;
sig->flags.revocable=1;
keyid_from_sk( sk, sig->keyid );
sig->pubkey_algo = sk->pubkey_algo;
sig->digest_algo = digest_algo;