1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-31 11:41:32 +01:00

Revamped preference handling

This commit is contained in:
Werner Koch 2001-08-10 14:04:32 +00:00
parent 57c1dbc21d
commit dc718d704f
20 changed files with 355 additions and 312 deletions

4
NEWS
View File

@ -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)
------------------------------------------------

1
THANKS
View File

@ -139,6 +139,7 @@ Philippe Laliberte arsphl@oeil.qc.ca
Peter Fales psfales@lucent.com
Peter Gutmann pgut001@cs.auckland.ac.nz
Peter Marschall Peter.Marschall@gedos.de
Peter Valchev pvalchev@openbsd.org
Piotr Krukowiecki piotr@pingu.ii.uj.edu.pl
QingLong qinglong@bolizm.ihep.su
Ralph Gillen gillen@theochem.uni-duesseldorf.de

View File

@ -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

View File

@ -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

View File

@ -1,3 +1,37 @@
2001-08-10 Werner Koch <wk@gnupg.org>
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 <wk@gnupg.org>
* build-packet.c (build_sig_subpkt): Fixed calculation of

View File

@ -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 {

View File

@ -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 );

View File

@ -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,

View File

@ -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 );

View File

@ -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;
@ -183,18 +212,6 @@ typedef struct {
char data[1];
} 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;
@ -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 );

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 );

View File

@ -1,3 +1,8 @@
2001-08-09 Werner Koch <wk@gnupg.org>
* config.links: Added configuraton for powerpc-openbsd. By Peter
Valchev
2001-07-09 Werner Koch <wk@gnupg.org>
* config.links: Changed the way the list of files to be

View File

@ -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"