diff options
author | Werner Koch <[email protected]> | 2001-08-10 14:04:32 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2001-08-10 14:04:32 +0000 |
commit | dc718d704fb66a91404ad170e733b88958489b71 (patch) | |
tree | c76b6de901944de26f36eac5c660c31599895e6b | |
parent | fixed silly allocation bug (diff) | |
download | gnupg-dc718d704fb66a91404ad170e733b88958489b71.tar.gz gnupg-dc718d704fb66a91404ad170e733b88958489b71.zip |
Revamped preference handling
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | THANKS | 1 | ||||
-rw-r--r-- | doc/DETAILS | 2 | ||||
-rw-r--r-- | doc/gpg.sgml | 2 | ||||
-rw-r--r-- | g10/ChangeLog | 34 | ||||
-rw-r--r-- | g10/encode.c | 2 | ||||
-rw-r--r-- | g10/free-packet.c | 81 | ||||
-rw-r--r-- | g10/getkey.c | 141 | ||||
-rw-r--r-- | g10/keyedit.c | 69 | ||||
-rw-r--r-- | g10/packet.h | 47 | ||||
-rw-r--r-- | g10/parse-packet.c | 4 | ||||
-rw-r--r-- | g10/pkclist.c | 55 | ||||
-rw-r--r-- | g10/pubkey-enc.c | 67 | ||||
-rw-r--r-- | g10/sign.c | 2 | ||||
-rw-r--r-- | g10/tdbio.c | 2 | ||||
-rw-r--r-- | g10/tdbio.h | 2 | ||||
-rw-r--r-- | g10/trustdb.c | 136 | ||||
-rw-r--r-- | g10/trustdb.h | 7 | ||||
-rw-r--r-- | mpi/ChangeLog | 5 | ||||
-rw-r--r-- | mpi/config.links | 4 |
20 files changed, 355 insertions, 312 deletions
@@ -16,6 +16,10 @@ primary UID, "setpref" and "updpref" can be used to change the preferences. + * Fixed the preference handling; since 1.0.5 they were erroneously + matched against against the latest user ID and not the given one. + + Noteworthy changes in version 1.0.6 (2001-05-29) ------------------------------------------------ @@ -139,6 +139,7 @@ Philippe Laliberte [email protected] Peter Fales [email protected] Peter Gutmann [email protected] Peter Marschall [email protected] +Peter Valchev [email protected] Piotr Krukowiecki [email protected] QingLong [email protected] Ralph Gillen [email protected] diff --git a/doc/DETAILS b/doc/DETAILS index aefc8adfd..aaccda6ce 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -507,7 +507,7 @@ the DB is always of type 1 and this is the only record of this type. Record type 5: (pref record) -------------- - Informations about preferences + This record type is not anymore used. 1 byte value 5 1 byte reserved diff --git a/doc/gpg.sgml b/doc/gpg.sgml index 80413283c..ae1165765 100644 --- a/doc/gpg.sgml +++ b/doc/gpg.sgml @@ -354,6 +354,7 @@ List preferences.</para></listitem></varlistentry> <term>showpref</term> <listitem><para> More verbose preferences listing.</para></listitem></varlistentry> + <varlistentry> <term>setpref &ParmString;</term> <listitem><para> Set the list of user ID preferences to &ParmString;, this should be @@ -363,6 +364,7 @@ preferences to nil. Only available algorithms are allowed. This command just initializes an internal list and does not change anything unless another command which changes the self-signatures is used. </para></listitem></varlistentry> + <varlistentry> <term>updpref</term> <listitem><para> Change the preferences of all user IDs (or just of the selected ones diff --git a/g10/ChangeLog b/g10/ChangeLog index 05a3a42e5..fea17b882 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,37 @@ +2001-08-10 Werner Koch <[email protected]> + + Revamped the preference handling. + + * packet.h (prefitem_t, preftype_t): New. + (PKT_public_key): Added a uid field. + (PKT_user_id): Added field to store preferences and a reference + counter. + * parse-packet.c (parse_user_id,parse_photo_id): Initialize them + * free-packet.c (free_user_id): Free them. + (copy_user_id): Removed. + (scopy_user_id): New. + (cmp_user_ids): Optimized for identical pointers. + (release_public_key_parts): Release the uid. + (copy_public_key_with_new_namehash): Removed. + (copy_prefs): New. + * keyedit.c (menu_adduid): Use the new shallow copy user id. + (show_prefs): Adjusted implementation. + (keyedit_menu): No more need to update the trustdb after changing + preferences. + * getkey.c (fixup_uidnode): Store preferences. + (find_by_name): Return a user id packet and remove namehash stuff. + (lookup): Removed the unused namehash stuff. + (finish_lookup): Added foundu arg. + (pk_from_block): Removed the namehash arg and changed all callers. + (merge_selfsigs): Copy prefs to all keys. + * trustdb.c (get_pref_data): Removed. + (is_algo_in_prefs): Removed. + (make_pref_record): Deleted and removed all class. + * pkclist.c (select_algo_from_prefs): Adjusted for the new + preference implementation. + * pubkey-enc.c (is_algo_in_prefs): New. + (get_it): Use that new function. + 2001-08-09 Werner Koch <[email protected]> * build-packet.c (build_sig_subpkt): Fixed calculation of diff --git a/g10/encode.c b/g10/encode.c index 3b7d30b69..5726be5a4 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -351,7 +351,7 @@ encode_crypt( const char *filename, STRLIST remusr ) /* register the compress filter */ if( do_compress ) { - int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR ); + int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_ZIP ); if( !compr_algo ) ; /* don't use compression */ else { diff --git a/g10/free-packet.c b/g10/free-packet.c index de3568825..de5b421b6 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -77,10 +77,18 @@ release_public_key_parts( PKT_public_key *pk ) mpi_free( pk->pkey[i] ); pk->pkey[i] = NULL; } + if (pk->prefs) { + m_free (pk->prefs); + pk->prefs = NULL; + } if( pk->namehash ) { m_free(pk->namehash); pk->namehash = NULL; } + if (pk->user_id) { + free_user_id (pk->user_id); + pk->user_id = NULL; + } } @@ -106,24 +114,42 @@ cp_subpktarea (subpktarea_t *s ) return d; } +/* + * Return a copy of the preferences + */ +prefitem_t * +copy_prefs (const prefitem_t *prefs) +{ + size_t n; + prefitem_t *new; + + if (!prefs) + return NULL; + + for (n=0; prefs[n].type; n++) + ; + new = m_alloc ( sizeof (*new) * (n+1)); + for (n=0; prefs[n].type; n++) { + new[n].type = prefs[n].type; + new[n].value = prefs[n].value; + } + new[n].type = PREFTYPE_NONE; + new[n].value = 0; + + return new; +} + PKT_public_key * -copy_public_key_new_namehash( PKT_public_key *d, PKT_public_key *s, - const byte *namehash ) +copy_public_key ( PKT_public_key *d, PKT_public_key *s) { int n, i; if( !d ) d = m_alloc(sizeof *d); memcpy( d, s, sizeof *d ); - if( namehash ) { - d->namehash = m_alloc( 20 ); - memcpy(d->namehash, namehash, 20 ); - } - else if( s->namehash ) { - d->namehash = m_alloc( 20 ); - memcpy(d->namehash, s->namehash, 20 ); - } + d->user_id = scopy_user_id (s->user_id); + d->prefs = copy_prefs (s->prefs); n = pubkey_get_npkey( s->pubkey_algo ); if( !n ) d->pkey[0] = mpi_copy(s->pkey[0]); @@ -134,12 +160,6 @@ copy_public_key_new_namehash( PKT_public_key *d, PKT_public_key *s, return d; } -PKT_public_key * -copy_public_key( PKT_public_key *d, PKT_public_key *s ) -{ - return copy_public_key_new_namehash( d, s, NULL ); -} - /**************** * Replace all common parts of a sk by the one from the public key. * This is a hack and a better solution will be to just store the real secret @@ -183,13 +203,15 @@ copy_signature( PKT_signature *d, PKT_signature *s ) } +/* + * shallow copy of the user ID + */ PKT_user_id * -copy_user_id( PKT_user_id *d, PKT_user_id *s ) +scopy_user_id (PKT_user_id *s) { - if( !d ) - d = m_alloc(sizeof *d + s->len - 1 ); - memcpy( d, s, sizeof *d + s->len - 1 ); - return d; + if (s) + s->ref++; + return s; } @@ -240,11 +262,17 @@ free_comment( PKT_comment *rem ) } void -free_user_id( PKT_user_id *uid ) +free_user_id (PKT_user_id *uid) { - if( uid->photo ) - m_free( uid->photo ); - m_free(uid); + assert (uid->ref > 0); + if (--uid->ref) + return; + + if (uid->photo) + m_free (uid->photo); + if (uid->prefs) + m_free (uid->prefs); + m_free (uid); } void @@ -466,6 +494,9 @@ cmp_user_ids( PKT_user_id *a, PKT_user_id *b ) { int res; + if ( a == b ) + return 0; + res = a->len - b->len; if( !res ) res = memcmp( a->name, b->name, a->len ); diff --git a/g10/getkey.c b/g10/getkey.c index 598b33b26..c9d1b874b 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -358,15 +358,14 @@ getkey_disable_caches() static void -pk_from_block ( GETKEY_CTX ctx, - PKT_public_key *pk, KBNODE keyblock, const char *namehash ) +pk_from_block ( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE keyblock ) { KBNODE a = ctx->found_key ? ctx->found_key : keyblock; assert ( a->pkt->pkttype == PKT_PUBLIC_KEY || a->pkt->pkttype == PKT_PUBLIC_SUBKEY ); - copy_public_key_new_namehash( pk, a->pkt->pkt.public_key, namehash); + copy_public_key ( pk, a->pkt->pkt.public_key ); } static void @@ -435,7 +434,7 @@ get_pubkey( PKT_public_key *pk, u32 *keyid ) ctx.req_usage = pk->req_usage; rc = lookup( &ctx, &kb, 0 ); if ( !rc ) { - pk_from_block ( &ctx, pk, kb, NULL ); + pk_from_block ( &ctx, pk, kb ); } get_pubkey_end( &ctx ); release_kbnode ( kb ); @@ -925,7 +924,7 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist, } rc = lookup( ctx, ret_kb, 0 ); if ( !rc && pk ) { - pk_from_block ( ctx, pk, *ret_kb, NULL /* FIXME need to get the namehash*/ ); + pk_from_block ( ctx, pk, *ret_kb ); } } @@ -972,7 +971,7 @@ get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock ) rc = lookup( ctx, ret_keyblock, 0 ); if ( !rc && pk && ret_keyblock ) - pk_from_block ( ctx, pk, *ret_keyblock, NULL ); + pk_from_block ( ctx, pk, *ret_keyblock ); return rc; } @@ -1020,7 +1019,7 @@ get_pubkey_byfprint( PKT_public_key *pk, memcpy( ctx.items[0].fprint, fprint, fprint_len ); rc = lookup( &ctx, &kb, 0 ); if (!rc && pk ) - pk_from_block ( &ctx, pk, kb, NULL ); + pk_from_block ( &ctx, pk, kb ); release_kbnode ( kb ); get_pubkey_end( &ctx ); } @@ -1399,14 +1398,23 @@ merge_keys_and_selfsig( KBNODE keyblock ) } } - +/* + * Apply information from SIGNODE (which is the valid self-signature + * associated with that UID) to the UIDNODE: + * - wether the UID has been revoked + * - assumed creation date of the UID + * - temporary store the keyflags here + * - temporary store the key expiration time here + * - mark whether the primary user ID flag hat been set. + * - store the preferences + */ static void fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) { PKT_user_id *uid = uidnode->pkt->pkt.user_id; PKT_signature *sig = signode->pkt->pkt.signature; - const byte *p; - size_t n; + const byte *p, *sym, *hash, *zip; + size_t n, nsym, nhash, nzip; uid->created = 0; /* not created == invalid */ if ( IS_UID_REV ( sig ) ) { @@ -1435,7 +1443,7 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) } /* Set the primary user ID flag - we will later wipe out some - * of them to only have one in out keyblock */ + * of them to only have one in our keyblock */ uid->is_primary = 0; p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PRIMARY_UID, NULL ); if ( p && *p ) @@ -1445,6 +1453,43 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) * there should be no security problem with this. * For now we only look at the hashed one. */ + + /* now build the preferences list. We try to get the preferences + * from the hashed list but if there are no such preferences, we + * try to get them from the unhashed list. There is no risk with + * that, because our implementation comes only with strong + * algorithms and it woulkd be fruitless for an attacker to insert + * an weak algorithm. */ + p = parse_sig_subpkt2 ( sig, SIGSUBPKT_PREF_SYM, &n ); + sym = p; nsym = p?n:0; + p = parse_sig_subpkt2 ( sig, SIGSUBPKT_PREF_HASH, &n ); + hash = p; nhash = p?n:0; + p = parse_sig_subpkt2 ( sig, SIGSUBPKT_PREF_COMPR, &n ); + zip = p; nzip = p?n:0; + if (uid->prefs) + m_free (uid->prefs); + n = nsym + nhash + nzip; + if (!n) + uid->prefs = NULL; + else { + uid->prefs = m_alloc (sizeof (*uid->prefs) * (n+1)); + n = 0; + for (; nsym; nsym--, n++) { + uid->prefs[n].type = PREFTYPE_SYM; + uid->prefs[n].value = *sym++; + } + for (; nhash; nhash--, n++) { + uid->prefs[n].type = PREFTYPE_HASH; + uid->prefs[n].value = *hash++; + } + for (; nzip; nzip--, n++) { + uid->prefs[n].type = PREFTYPE_ZIP; + uid->prefs[n].value = *sym++; + } + uid->prefs[n].type = PREFTYPE_NONE; /* end of list marker */ + uid->prefs[n].value = 0; + } + } static void @@ -1800,6 +1845,7 @@ merge_selfsigs( KBNODE keyblock ) KBNODE k; int revoked; PKT_public_key *main_pk; + prefitem_t *prefs; if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY ) { if (keyblock->pkt->pkttype == PKT_SECRET_KEY ) { @@ -1836,6 +1882,33 @@ merge_selfsigs( KBNODE keyblock ) merge_selfsigs_subkey ( keyblock, k ); } } + + /* set the preference list of all keys to those of the primary + * user ID. Note: we use these preferences when we don't know by + * which user ID the key has been selected. + * fixme: we should keep atoms of commonly used preferences or + * use reference counting to optimize the preference lists storage. + * FIXME: it might be better to use the intersection of + * all preferences. + */ + prefs = NULL; + for (k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next) { + if (k->pkt->pkttype == PKT_USER_ID + && k->pkt->pkt.user_id->is_primary) { + prefs = k->pkt->pkt.user_id->prefs; + break; + } + } + for(k=keyblock; k; k = k->next ) { + if ( k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + PKT_public_key *pk = k->pkt->pkt.public_key; + if (pk->prefs) + m_free (pk->prefs); + pk->prefs = copy_prefs (prefs); + } + } + } @@ -1955,9 +2028,8 @@ premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock ) ************* Find stuff *********************** ************************************************/ -static int -find_by_name( KBNODE keyblock, const char *name, - int mode, byte *namehash ) +static PKT_user_id * +find_by_name( KBNODE keyblock, const char *name, int mode ) { KBNODE k; @@ -1965,23 +2037,11 @@ find_by_name( KBNODE keyblock, const char *name, if( k->pkt->pkttype == PKT_USER_ID && !compare_name( k->pkt->pkt.user_id->name, k->pkt->pkt.user_id->len, name, mode)) { - /* we found a matching name, look for the key */ - if( k->pkt->pkt.user_id->photo ) { - /* oops: this can never happen */ - rmd160_hash_buffer( namehash, - k->pkt->pkt.user_id->photo, - k->pkt->pkt.user_id->photolen ); - } - else { - rmd160_hash_buffer( namehash, - k->pkt->pkt.user_id->name, - k->pkt->pkt.user_id->len ); - } - return 1; + return k->pkt->pkt.user_id; } } - return 0; + return NULL; } @@ -2068,7 +2128,7 @@ find_by_fpr( KBNODE keyblock, const char *name, int mode ) */ static int -finish_lookup( GETKEY_CTX ctx, KBNODE foundk ) +finish_lookup( GETKEY_CTX ctx, KBNODE foundk, PKT_user_id *foundu ) { KBNODE keyblock = ctx->keyblock; KBNODE k; @@ -2098,6 +2158,10 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk ) } if (!req_usage) { + PKT_public_key *pk = foundk->pkt->pkt.public_key; + if (pk->user_id) + free_user_id (pk->user_id); + pk->user_id = scopy_user_id (foundu); ctx->found_key = foundk; cache_user_id( keyblock ); return 1; /* found */ @@ -2200,6 +2264,13 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk ) log_debug( "\tusing key %08lX\n", (ulong)keyid_from_pk( latest_key->pkt->pkt.public_key, NULL) ); + if (latest_key) { + PKT_public_key *pk = latest_key->pkt->pkt.public_key; + if (pk->user_id) + free_user_id (pk->user_id); + pk->user_id = scopy_user_id (foundu); + } + ctx->found_key = latest_key; if (latest_key != keyblock && opt.verbose) { @@ -2220,8 +2291,6 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ) { int rc; int oldmode = set_packet_list_mode(0); - byte namehash[20]; - int use_namehash=0; KBNODE secblock = NULL; /* helper */ int no_suitable_key = 0; @@ -2261,12 +2330,12 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ) for(n=0; n < ctx->nitems; n++, item++ ) { KBNODE k = NULL; int found = 0; + PKT_user_id *found_uid = NULL; if( item->mode < 10 ) { - found = find_by_name( ctx->keyblock, - item->name, item->mode, - namehash ); - use_namehash = found; + found_uid = find_by_name( ctx->keyblock, + item->name, item->mode ); + found = !!found_uid; } else if( item->mode >= 10 && item->mode <= 12 ) { k = find_by_keyid( ctx->keyblock, @@ -2287,7 +2356,7 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ) if( found ) { /* this keyblock looks fine - do further investigation */ merge_selfsigs ( ctx->keyblock ); - if ( finish_lookup( ctx, k ) ) { + if ( finish_lookup( ctx, k, found_uid ) ) { no_suitable_key = 0; if ( secmode ) { merge_public_with_secret ( ctx->keyblock, diff --git a/g10/keyedit.c b/g10/keyedit.c index 8f4dccf4c..872a80484 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -40,7 +40,7 @@ #include "status.h" #include "i18n.h" -static void show_prefs( KBNODE keyblock, PKT_user_id *uid, int verbose ); +static void show_prefs( PKT_user_id *uid, int verbose ); static void show_key_with_all_names( KBNODE keyblock, int only_marked, int with_fpr, int with_subkeys, int with_prefs ); static void show_key_and_fingerprint( KBNODE keyblock ); @@ -974,7 +974,6 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, _("Really update the preferences? "))){ if ( menu_set_preferences (keyblock, sec_keyblock) ) { - update_trust_record (keyblock, 0, NULL); merge_keys_and_selfsig (keyblock); modified = 1; redisplay = 1; @@ -1065,49 +1064,31 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, * show preferences of a public keyblock. */ static void -show_prefs( KBNODE keyblock, PKT_user_id *uid, int verbose ) +show_prefs (PKT_user_id *uid, int verbose) { - KBNODE node = find_kbnode( keyblock, PKT_PUBLIC_KEY ); - PKT_public_key *pk; - byte *p; + const prefitem_t *prefs; int i; - size_t n; - byte namehash[20]; - - if( !node ) - return; /* is a secret keyblock */ - pk = node->pkt->pkt.public_key; - if( !pk->local_id ) { - log_error("oops: no LID\n"); - return; - } - - if( uid->photo ) - rmd160_hash_buffer( namehash, uid->photo, uid->photolen ); - else - rmd160_hash_buffer( namehash, uid->name, uid->len ); - - p = get_pref_data( pk->local_id, namehash, &n ); - if( !p ) - return; + if( !uid || !uid->prefs ) + return; + prefs = uid->prefs; if (verbose) { int any, des_seen=0; tty_printf (" Cipher: "); - for(i=any=0; i < n; i+=2 ) { - if( p[i] == PREFTYPE_SYM ) { - const char *s = cipher_algo_to_string (p[i+1]); + for(i=any=0; prefs[i].type; i++ ) { + if( prefs[i].type == PREFTYPE_SYM ) { + const char *s = cipher_algo_to_string (prefs[i].value); if (any) tty_printf (", "); any = 1; /* We don't want to display strings for experimental algos */ - if (s && p[i+1] < 100 ) + if (s && prefs[i].value < 100 ) tty_printf ("%s", s ); else - tty_printf ("[%d]", p[i+1]); - if (p[i+1] == CIPHER_ALGO_3DES ) + tty_printf ("[%d]", prefs[i].value); + if (prefs[i].value == CIPHER_ALGO_3DES ) des_seen = 1; } } @@ -1117,34 +1098,32 @@ show_prefs( KBNODE keyblock, PKT_user_id *uid, int verbose ) tty_printf ("3DES"); } tty_printf ("\n Hash: "); - for(i=any=0; i < n; i+=2 ) { - if( p[i] == PREFTYPE_HASH ) { - const char *s = digest_algo_to_string (p[i+1]); + for(i=any=0; prefs[i].type; i++ ) { + if( prefs[i].type == PREFTYPE_HASH ) { + const char *s = digest_algo_to_string (prefs[i].value); if (any) tty_printf (", "); any = 1; /* We don't want to display strings for experimental algos */ - if (s && p[i+1] < 100 ) + if (s && prefs[i].value < 100 ) tty_printf ("%s", s ); else - tty_printf ("[%d]", p[i+1]); + tty_printf ("[%d]", prefs[i].value); } } tty_printf("\n"); } else { tty_printf(" "); - for(i=0; i < n; i+=2 ) { - if( p[i] ) - tty_printf( " %c%d", p[i] == PREFTYPE_SYM ? 'S' : - p[i] == PREFTYPE_HASH ? 'H' : - p[i] == PREFTYPE_COMPR ? 'Z':'?', p[i+1]); + for(i=0; prefs[i].type; i++ ) { + tty_printf( " %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' : + prefs[i].type == PREFTYPE_HASH ? 'H' : + prefs[i].type == PREFTYPE_ZIP ? 'Z':'?', + prefs[i].value); } tty_printf("\n"); } - - m_free(p); } @@ -1244,7 +1223,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, tty_print_utf8_string( uid->name, uid->len ); tty_printf("\n"); if( with_prefs ) - show_prefs( keyblock, uid, with_prefs == 2 ); + show_prefs (uid, with_prefs == 2); } } } @@ -1355,7 +1334,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock ) /* insert/append to secret keyblock */ pkt = m_alloc_clear( sizeof *pkt ); pkt->pkttype = PKT_USER_ID; - pkt->pkt.user_id = copy_user_id(NULL, uid); + pkt->pkt.user_id = scopy_user_id(uid); node = new_kbnode(pkt); if( sec_where ) insert_kbnode( sec_where, node, 0 ); diff --git a/g10/packet.h b/g10/packet.h index 737c4a586..e80711759 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -62,6 +62,17 @@ typedef enum { CTRLPKT_PLAINTEXT_MARK =3 } ctrlpkttype_t; +typedef enum { + PREFTYPE_NONE = 0, + PREFTYPE_SYM = 1, + PREFTYPE_HASH = 2, + PREFTYPE_ZIP = 3 +} preftype_t; + +typedef struct { + byte type; + byte value; +} prefitem_t; typedef struct { int mode; @@ -102,6 +113,7 @@ typedef struct { byte data[1]; } subpktarea_t; + typedef struct { ulong local_id; /* internal use, valid if > 0 */ struct { @@ -123,6 +135,21 @@ typedef struct { } PKT_signature; +typedef struct { + int ref; /* reference counter */ + int len; /* length of the name */ + char *photo; /* if this is not NULL, the packet is a photo ID */ + int photolen; /* and the length of the photo */ + int help_key_usage; + u32 help_key_expire; + int is_primary; + int is_revoked; + prefitem_t *prefs; /* list of preferences (may be NULL)*/ + u32 created; /* according to the self-signature */ + char name[1]; +} PKT_user_id; + + /**************** * Note about the pkey/skey elements: We assume that the secret keys * has the same elemts as the public key at the begin of the array, so @@ -144,7 +171,9 @@ typedef struct { ulong local_id; /* internal use, valid if > 0 */ u32 main_keyid[2]; /* keyid of the primary key */ u32 keyid[2]; /* calculated by keyid_from_pk() */ + prefitem_t *prefs; /* list of preferences (may be NULL) */ byte *namehash; /* if != NULL: found by this name */ + PKT_user_id *user_id; /* if != NULL: found by that uid */ MPI pkey[PUBKEY_MAX_NPKEY]; } PKT_public_key; @@ -184,18 +213,6 @@ typedef struct { } PKT_comment; typedef struct { - int len; /* length of the name */ - char *photo; /* if this is not NULL, the packet is a photo ID */ - int photolen; /* and the length of the photo */ - int help_key_usage; - u32 help_key_expire; - int is_primary; - int is_revoked; - u32 created; /* according to the self-signature */ - char name[1]; -} PKT_user_id; - -typedef struct { u32 len; /* reserved */ byte new_ctb; byte algorithm; @@ -365,14 +382,12 @@ void free_secret_key( PKT_secret_key *sk ); void free_user_id( PKT_user_id *uid ); void free_comment( PKT_comment *rem ); void free_packet( PACKET *pkt ); +prefitem_t *copy_prefs (const prefitem_t *prefs); PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s ); -PKT_public_key *copy_public_key_new_namehash( PKT_public_key *d, - PKT_public_key *s, - const byte *namehash ); void copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk ); PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s ); PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s ); -PKT_user_id *copy_user_id( PKT_user_id *d, PKT_user_id *s ); +PKT_user_id *scopy_user_id (PKT_user_id *sd ); int cmp_public_keys( PKT_public_key *a, PKT_public_key *b ); int cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b ); int cmp_signatures( PKT_signature *a, PKT_signature *b ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 0c3ab6188..5461664f0 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1590,6 +1590,7 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) byte *p; packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + pktlen); + packet->pkt.user_id->ref = 1; packet->pkt.user_id->len = pktlen; packet->pkt.user_id->photo = NULL; packet->pkt.user_id->photolen = 0; @@ -1598,6 +1599,7 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) 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; for( ; pktlen; pktlen--, p++ ) @@ -1630,6 +1632,7 @@ parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) byte *p; packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + 30); + packet->pkt.user_id->ref = 1; sprintf( packet->pkt.user_id->name, "[image of size %lu]", pktlen ); packet->pkt.user_id->len = strlen(packet->pkt.user_id->name); packet->pkt.user_id->is_primary = 0; @@ -1637,6 +1640,7 @@ parse_photo_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) packet->pkt.user_id->created = 0; packet->pkt.user_id->help_key_usage = 0; packet->pkt.user_id->help_key_expire = 0; + packet->pkt.user_id->prefs = NULL; packet->pkt.user_id->photo = m_alloc(sizeof *packet->pkt.user_id + pktlen); packet->pkt.user_id->photolen = pktlen; diff --git a/g10/pkclist.c b/g10/pkclist.c index 45a40fe37..8c4fa6bac 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -1036,13 +1036,15 @@ algo_available( int preftype, int algo ) else if( preftype == PREFTYPE_HASH ) { return algo && !check_digest_algo( algo ); } - else if( preftype == PREFTYPE_COMPR ) { + else if( preftype == PREFTYPE_ZIP ) { return !algo || algo == 1 || algo == 2; } else return 0; } + + /**************** * Return -1 if we could not find an algorithm. */ @@ -1051,8 +1053,7 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype ) { PK_LIST pkr; u32 bits[8]; - byte *pref = NULL; - size_t npref; + const prefitem_t *prefs; int i, j; int compr_hack=0; int any; @@ -1065,43 +1066,38 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype ) u32 mask[8]; memset( mask, 0, 8 * sizeof *mask ); - if( !pkr->pk->local_id ) { /* try to set the local id */ - query_trust_info( pkr->pk, NULL ); - if( !pkr->pk->local_id ) { - log_debug("select_algo_from_prefs: can't get LID\n"); - continue; - } - } if( preftype == PREFTYPE_SYM ) mask[0] |= (1<<2); /* 3DES is implicitly there */ - m_free(pref); - pref = get_pref_data( pkr->pk->local_id, pkr->pk->namehash, &npref); + + if (pkr->pk->user_id) /* selected by user ID */ + prefs = pkr->pk->user_id->prefs; + else + prefs = pkr->pk->prefs; + any = 0; - if( pref ) { - #if 0 - log_hexdump("raw: ", pref, npref ); - #endif - for(i=0; i+1 < npref; i+=2 ) { - if( pref[i] == preftype ) { - mask[pref[i+1]/32] |= 1 << (pref[i+1]%32); + if( prefs ) { + for (i=0; prefs[i].type; i++ ) { + if( prefs[i].type == preftype ) { + mask[prefs[i].value/32] |= 1 << (prefs[i].value%32); any = 1; } } } - if( (!pref || !any) && preftype == PREFTYPE_COMPR ) { + + if( (!prefs || !any) && preftype == PREFTYPE_ZIP ) { mask[0] |= 3; /* asume no_compression and old pgp */ compr_hack = 1; } #if 0 - log_debug("mask=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", + log_debug("pref mask=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", (ulong)mask[7], (ulong)mask[6], (ulong)mask[5], (ulong)mask[4], (ulong)mask[3], (ulong)mask[2], (ulong)mask[1], (ulong)mask[0]); #endif for(i=0; i < 8; i++ ) bits[i] &= mask[i]; #if 0 - log_debug("bits=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", + log_debug("pref bits=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", (ulong)bits[7], (ulong)bits[6], (ulong)bits[5], (ulong)bits[4], (ulong)bits[3], (ulong)bits[2], (ulong)bits[1], (ulong)bits[0]); #endif @@ -1114,20 +1110,20 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype ) */ i = -1; any = 0; - if( pref ) { - for(j=0; j+1 < npref; j+=2 ) { - if( pref[j] == preftype ) { - if( (bits[pref[j+1]/32] & (1<<(pref[j+1]%32))) ) { - if( algo_available( preftype, pref[j+1] ) ) { + if( prefs ) { + for(j=0; prefs[j].type; j++ ) { + if( prefs[j].type == preftype ) { + if( (bits[prefs[j].value/32] & (1<<(prefs[j].value%32))) ) { + if( algo_available( preftype, prefs[j].value ) ) { any = 1; - i = pref[j+1]; + i = prefs[j].value; break; } } } } } - if( !pref || !any ) { + if( !prefs || !any ) { for(j=0; j < 256; j++ ) if( (bits[j/32] & (1<<(j%32))) ) { if( algo_available( preftype, j ) ) { @@ -1147,7 +1143,6 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype ) i = 1; /* yep; we can use compression algo 1 */ } - m_free(pref); return i; } diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 24dada94e..1d0b855d4 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -37,6 +37,29 @@ static int get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid ); + +/* check that the given algo is mentioned in one of the valid user IDs */ +static int +is_algo_in_prefs ( KBNODE keyblock, preftype_t type, int algo ) +{ + KBNODE k; + + for (k=keyblock; k; k=k->next) { + if (k->pkt->pkttype == PKT_USER_ID) { + PKT_user_id *uid = k->pkt->pkt.user_id; + prefitem_t *prefs = uid->prefs; + + if (uid->created && !uid->is_revoked && prefs ) { + for (; prefs->type; prefs++ ) + if (prefs->type == type && prefs->value == algo) + return 1; + } + } + } + return 0; +} + + /**************** * Get the session key from a pubkey enc paket and return * it in DEK, which should have been allocated in secure memory. @@ -175,29 +198,47 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid ) log_hexdump("DEK is:", dek->key, dek->keylen ); /* check that the algo is in the preferences and whether it has expired */ { - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); - if( (rc = get_pubkey( pk, keyid )) ) - log_error("public key problem: %s\n", g10_errstr(rc) ); - else if( !pk->local_id && query_trust_record(pk) ) - log_error("can't check algorithm against preferences\n"); + PKT_public_key *pk = NULL; + KBNODE pkb = get_pubkeyblock (keyid); + + if( !pkb ) { + rc = -1; + log_error("oops: public key not found for preference check\n"); + } else if( dek->algo != CIPHER_ALGO_3DES - && !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) ) { + && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) { /* Don't print a note while we are not on verbose mode, * the cipher is blowfish and the preferences have twofish * listed */ if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH - || !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, - CIPHER_ALGO_TWOFISH ) ) + || !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH)) log_info(_( "NOTE: cipher algorithm %d not found in preferences\n"), dek->algo ); } + if (!rc) { + KBNODE k; + + for (k=pkb; k; k = k->next) { + if (k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY){ + u32 aki[2]; + keyid_from_pk(k->pkt->pkt.public_key, aki); - if( !rc && pk->expiredate && pk->expiredate <= make_timestamp() ) { - log_info(_("NOTE: secret key %08lX expired at %s\n"), - (ulong)keyid[1], asctimestamp( pk->expiredate) ); - } + if (aki[0]==keyid[0] && aki[1]==keyid[1]) { + pk = k->pkt->pkt.public_key; + break; + } + } + } + if (!pk) + BUG (); + if ( pk->expiredate && pk->expiredate <= make_timestamp() ) { + log_info(_("NOTE: secret key %08lX expired at %s\n"), + (ulong)keyid[1], asctimestamp( pk->expiredate) ); + } + } /* FIXME: check wheter the key has been revoked and display * the revocation reason. Actually the user should know this himself, @@ -206,7 +247,7 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid ) * the message. The user can than watch out for snakes send by * one of those Eves outside his paradise :-) */ - free_public_key( pk ); + release_kbnode (pkb); rc = 0; } diff --git a/g10/sign.c b/g10/sign.c index 817099a84..bd3faf2b5 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -292,7 +292,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC )) ) goto leave; if( !old_style ) - compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR ); + compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_ZIP ); } /* prepare iobufs */ diff --git a/g10/tdbio.c b/g10/tdbio.c index 890d7ab8e..e9c9457dd 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -1161,7 +1161,7 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp ) if( *p ) fprintf(fp, " %c%d", *p == PREFTYPE_SYM ? 'S' : *p == PREFTYPE_HASH ? 'H' : - *p == PREFTYPE_COMPR ? 'Z' : '?', p[1]); + *p == PREFTYPE_ZIP ? 'Z' : '?', p[1]); } putc('\n', fp); break; diff --git a/g10/tdbio.h b/g10/tdbio.h index b18e9291f..d615ac687 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -125,7 +125,7 @@ struct trust_record { /* or 0 for a global pref record */ ulong next; /* points to next pref record */ byte data[ITEMS_PER_PREF_RECORD]; - } pref; + } pref; /* pref records are not anymore used! */ struct { /* signature record */ ulong lid; ulong next; /* recnno of next record or NULL for last one */ diff --git a/g10/trustdb.c b/g10/trustdb.c index 696db3c0e..b8a4d8b12 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1378,72 +1378,6 @@ make_sig_records( KBNODE keyblock, KBNODE uidnode, -/**************** - * Make a preference record (or a list of them) according to the supplied - * signature. - * Returns: The record number of the first pref record. - */ -static ulong -make_pref_record( PKT_signature *sig, ulong lid ) -{ - static struct { - sigsubpkttype_t subpkttype; - int preftype; - } ptable[] = { - { SIGSUBPKT_PREF_SYM, PREFTYPE_SYM }, - { SIGSUBPKT_PREF_HASH, PREFTYPE_HASH }, - { SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR }, - { 0, 0 } - }; - TRUSTREC *precs, **p_end, *p=NULL, *p2; - ulong precno; - int k, idx=0; - const byte *s; - size_t n; - - #if (ITEMS_PER_PREF_RECORD % 2) != 0 - #error ITEMS_PER_PREF_RECORD must have an even value - #endif - - precs = NULL; p_end = &precs; - for(k=0; ptable[k].subpkttype; k++ ) { - s = parse_sig_subpkt2( sig, ptable[k].subpkttype, &n ); - if( !s ) - continue; - for( ; n; n--, s++ ) { - if( !idx ) { - p = m_alloc_clear( sizeof *p ); - p->rectype = RECTYPE_PREF; - p->r.pref.lid = lid; - } - p->r.pref.data[idx++] = ptable[k].preftype; - p->r.pref.data[idx++] = *s; - if( idx >= ITEMS_PER_PREF_RECORD ) { - p->recnum = tdbio_new_recnum(); - *p_end = p; - p_end = &p->next; - idx = 0; - } - } - } - if( idx ) { - p->recnum = tdbio_new_recnum(); - *p_end = p; - p_end = &p->next; - } - - precno = precs? precs->recnum : 0; - /* write the precs and release the memory */ - for( p = precs; p ; p = p2 ) { - if( p->next ) - p->r.pref.next = p->next->recnum; - write_record( p ); - p2 = p->next; - m_free( p ); - } - return precno; -} - static ulong make_uid_records( KBNODE keyblock, ulong lid, u32 *keyid, u32 *min_expire, @@ -1480,7 +1414,7 @@ make_uid_records( KBNODE keyblock, ulong lid, u32 *keyid, u32 *min_expire, lid, &bestsig ); if( (u->r.uid.uidflags & UIDF_CHECKED) && (u->r.uid.uidflags & UIDF_VALID) ) { - u->r.uid.prefrec = bestsig? make_pref_record( bestsig, lid ) : 0; + u->r.uid.prefrec = 0; } /* the next test is really bad because we should modify @@ -1579,6 +1513,8 @@ do_update_trust_record( KBNODE keyblock, TRUSTREC *drec, for( recno=drec->r.dir.uidlist; recno; recno = urec.r.uid.next ) { read_record( recno, &urec, RECTYPE_UID ); for(r2=urec.r.uid.prefrec ; r2; r2 = prec.r.pref.next ) { + /* we don't use preference records any more, but all ones might + * still be there */ read_record( r2, &prec, RECTYPE_PREF ); delete_record( r2 ); } @@ -2748,69 +2684,3 @@ enum_cert_paths_print( void **context, FILE *fp, } -/* - * Return an allocated buffer with the preference values for - * the key with LID and the userid which is identified by the - * HAMEHASH or the first one if namehash is NULL. ret_n receives - * the length of the allocated buffer. Structure of the buffer is - * a repeated sequences of 2 bytes; where the first byte describes the - * type of the preference and the second one the value. The constants - * PREFTYPE_xxxx should be used to reference a type. - */ -byte * -get_pref_data( ulong lid, const byte *namehash, size_t *ret_n ) -{ - TRUSTREC rec; - ulong recno; - - init_trustdb(); - read_record( lid, &rec, RECTYPE_DIR ); - for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) { - read_record( recno, &rec, RECTYPE_UID ); - if( rec.r.uid.prefrec - && ( !namehash || !memcmp(namehash, rec.r.uid.namehash, 20) )) { - byte *buf; - /* found the correct one or the first one */ - read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF ); - if( rec.r.pref.next ) - log_info(_("WARNING: can't yet handle long pref records\n")); - buf = m_alloc( ITEMS_PER_PREF_RECORD ); - memcpy( buf, rec.r.pref.data, ITEMS_PER_PREF_RECORD ); - *ret_n = ITEMS_PER_PREF_RECORD; - return buf; - } - } - return NULL; -} - - - -/**************** - * Check whether the algorithm is in one of the pref records - */ -int -is_algo_in_prefs( ulong lid, int preftype, int algo ) -{ - TRUSTREC rec; - ulong recno; - int i; - byte *pref; - - init_trustdb(); - read_record( lid, &rec, RECTYPE_DIR ); - for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) { - read_record( recno, &rec, RECTYPE_UID ); - if( rec.r.uid.prefrec ) { - read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF ); - if( rec.r.pref.next ) - log_info(_("WARNING: can't yet handle long pref records\n")); - pref = rec.r.pref.data; - for(i=0; i+1 < ITEMS_PER_PREF_RECORD; i+=2 ) { - if( pref[i] == preftype && pref[i+1] == algo ) - return 1; - } - } - } - return 0; -} - diff --git a/g10/trustdb.h b/g10/trustdb.h index 367bbaa6c..183088723 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -37,11 +37,6 @@ #define TRUST_FLAG_DISABLED 128 /* d: key/uid disabled */ -#define PREFTYPE_SYM 1 -#define PREFTYPE_HASH 2 -#define PREFTYPE_COMPR 3 - - /*-- trustdb.c --*/ void list_trust_path( const char *username ); void register_trusted_key( const char *string ); @@ -59,8 +54,6 @@ void enum_cert_paths_print( void **context, FILE *fp, int refresh, ulong selected_lid ); unsigned get_ownertrust( ulong lid ); int get_ownertrust_info( ulong lid ); -byte *get_pref_data( ulong lid, const byte *namehash, size_t *ret_n ); -int is_algo_in_prefs( ulong lid, int preftype, int algo ); int keyid_from_lid( ulong lid, u32 *keyid ); ulong lid_from_keyblock( KBNODE keyblock ); int query_trust_record( PKT_public_key *pk ); diff --git a/mpi/ChangeLog b/mpi/ChangeLog index ec007d677..9a60c3727 100644 --- a/mpi/ChangeLog +++ b/mpi/ChangeLog @@ -1,3 +1,8 @@ +2001-08-09 Werner Koch <[email protected]> + + * config.links: Added configuraton for powerpc-openbsd. By Peter + Valchev + 2001-07-09 Werner Koch <[email protected]> * config.links: Changed the way the list of files to be diff --git a/mpi/config.links b/mpi/config.links index 6efd38907..6f2f63363 100644 --- a/mpi/config.links +++ b/mpi/config.links @@ -198,8 +198,8 @@ case "${target}" in path="powerpc32" ;; - powerpc*-*-netbsd*) - echo '/* configured NetBSD on powerpc */' >>./mpi/asm-syntax.h + powerpc*-*-netbsd* | powerpc*-*-openbsd*) + echo '/* configured {Open,Net}BSD on powerpc */' >>./mpi/asm-syntax.h echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h cat $srcdir/mpi/powerpc32/syntax.h >>./mpi/asm-syntax.h mpi_sflags="-Wa,-mppc" |