diff options
Diffstat (limited to 'g10/ringedit.c')
-rw-r--r-- | g10/ringedit.c | 259 |
1 files changed, 93 insertions, 166 deletions
diff --git a/g10/ringedit.c b/g10/ringedit.c index b2193e7e2..5e610e583 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -84,11 +84,12 @@ static RESTBL resource_table[MAX_RESOURCES]; static int default_public_resource; static int default_secret_resource; -static int search( PACKET *pkt, KBPOS *kbpos, int secret ); +static int search (PKT_public_key *req_pk, u32 *req_keyid, + KBPOS *kbpos, int secret); -static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf, - const char *fname ); +static int keyring_search (PKT_public_key *req_pk, u32 *req_keyid, + KBPOS *kbpos, IOBUF iobuf, const char *fname ); static int keyring_read( KBPOS *kbpos, KBNODE *ret_root ); static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs ); static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root ); @@ -97,7 +98,7 @@ static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root ); static int do_gdbm_store( KBPOS *kbpos, KBNODE root, int update ); static int do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, const byte *fpr, int fprlen ); -static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid ); +/*static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid );*/ static int do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root ); static int do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root ); #endif @@ -464,26 +465,31 @@ get_writable_keyblock_file( int secret ) * Returns: 0 if found, -1 if not found or an errorcode. */ static int -search( PACKET *pkt, KBPOS *kbpos, int secret ) +search (PKT_public_key *req_pk, u32 *req_keyid, KBPOS *kbpos, int secret) { int i, rc, last_rc=-1; for(i=0; i < MAX_RESOURCES; i++ ) { if( resource_table[i].used && !resource_table[i].secret == !secret ) { switch( resource_table[i].rt ) { - case rt_RING: - rc = keyring_search( pkt, kbpos, resource_table[i].iobuf, - resource_table[i].fname ); - break; - #ifdef HAVE_LIBGDBM + case rt_RING: + rc = keyring_search (req_pk, req_keyid, + kbpos, resource_table[i].iobuf, + resource_table[i].fname ); + + break; + #ifdef HAVE_LIBGDBM case rt_GDBM: { - PKT_public_key *req_pk = pkt->pkt.public_key; byte fpr[20]; size_t fprlen; - - fingerprint_from_pk( req_pk, fpr, &fprlen ); - rc = do_gdbm_locate( resource_table[i].dbf, - kbpos, fpr, fprlen ); + + if (!req_pk) + rc = G10ERR_UNSUPPORTED; + else { + fingerprint_from_pk( req_pk, fpr, &fprlen ); + rc = do_gdbm_locate( resource_table[i].dbf, + kbpos, fpr, fprlen ); + } } break; #endif @@ -514,20 +520,12 @@ search( PACKET *pkt, KBPOS *kbpos, int secret ) int find_keyblock_byname( KBPOS *kbpos, const char *username ) { - PACKET pkt; PKT_public_key *pk = m_alloc_clear( sizeof *pk ); int rc; rc = get_pubkey_byname( NULL, pk, username, NULL ); - if( rc ) { - free_public_key(pk); - return rc; - } - - init_packet( &pkt ); - pkt.pkttype = PKT_PUBLIC_KEY; - pkt.pkt.public_key = pk; - rc = search( &pkt, kbpos, 0 ); + if (!rc) + rc = search( pk, NULL, kbpos, 0 ); free_public_key(pk); return rc; } @@ -540,30 +538,22 @@ find_keyblock_byname( KBPOS *kbpos, const char *username ) int find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk ) { - PACKET pkt; int rc; - init_packet( &pkt ); - pkt.pkttype = PKT_PUBLIC_KEY; - pkt.pkt.public_key = pk; - rc = search( &pkt, kbpos, 0 ); + rc = search( pk, NULL, kbpos, 0 ); return rc; } /**************** - * Combined function to search for a key and get the position - * of the keyblock. + * Combined function to search for a secret key and get the position + * of the keyblock. */ int -find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk ) +find_secret_keyblock_bypk (KBPOS *kbpos, PKT_public_key *pk) { - PACKET pkt; int rc; - init_packet( &pkt ); - pkt.pkttype = PKT_SECRET_KEY; - pkt.pkt.secret_key = sk; - rc = search( &pkt, kbpos, 0 ); + rc = search (pk, NULL, kbpos, 1); return rc; } @@ -575,113 +565,27 @@ find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk ) int find_secret_keyblock_byname( KBPOS *kbpos, const char *username ) { - PACKET pkt; - PKT_secret_key *sk = m_alloc_clear( sizeof *sk ); + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); int rc; - rc = get_seckey_byname( sk, username, 0 ); - if( rc ) { - free_secret_key(sk); - return rc; - } - - init_packet( &pkt ); - pkt.pkttype = PKT_SECRET_KEY; - pkt.pkt.secret_key = sk; - rc = search( &pkt, kbpos, 1 ); - free_secret_key(sk); + rc = get_pubkey_byname( NULL, pk, username, NULL ); + if (!rc) + rc = search (pk, NULL, kbpos, 1); + free_public_key (pk); return rc; } - -/**************** - * Locate a keyblock in a database which is capable of direct access - * Put all information into KBPOS, which can be later be to access this - * key block. - * This function looks into all registered keyblock sources. - * - * Returns: 0 if found, - * -1 if not found - * G10ERR_UNSUPPORTED if no resource is able to handle this - * or another errorcode. +/* + * This function locates the secret keyblock without doing a public + * keyring check fist. It is useful in certain situations and much + * faster than the generic solution. */ int -locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, int fprlen, int secret ) -{ - RESTBL *rentry; - int i, rc, any=0, last_rc=-1; - - - for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) { - if( rentry->used && !rentry->secret == !secret ) { - kbpos->rt = rentry->rt; - switch( rentry->rt ) { - #ifdef HAVE_LIBGDBM - case rt_GDBM: - any = 1; - rc = do_gdbm_locate( rentry->dbf, kbpos, fpr, fprlen ); - break; - #endif - default: - rc = G10ERR_UNSUPPORTED; - break; - } - - if( !rc ) { - kbpos->resno = i; - kbpos->fp = NULL; - return 0; - } - else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) { - log_error("error searching resource %d: %s\n", - i, g10_errstr(rc)); - last_rc = rc; - } - } - } - - return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc; -} - - -int -locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, int shortkid, int secret ) +find_secret_keyblock_direct (KBPOS *kbpos, u32 *keyid) { - RESTBL *rentry; - int i, rc, any=0, last_rc=-1; - - if( shortkid ) - return G10ERR_UNSUPPORTED; - - for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) { - if( rentry->used && !rentry->secret == !secret ) { - kbpos->rt = rentry->rt; - switch( rentry->rt ) { - #ifdef HAVE_LIBGDBM - case rt_GDBM: - any = 1; - rc = do_gdbm_locate_by_keyid( rentry->dbf, kbpos, keyid ); - break; - #endif - default: - rc = G10ERR_UNSUPPORTED; - break; - } - - if( !rc ) { - kbpos->resno = i; - kbpos->fp = NULL; - return 0; - } - else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) { - log_error("error searching resource %d: %s\n", - i, g10_errstr(rc)); - last_rc = rc; - } - } - } - - return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc; + int rc; + rc = search (NULL, keyid, kbpos, 1); + return rc; } @@ -1065,21 +969,16 @@ scan_user_file_read( SCAN_USER_HANDLE hd, byte *fpr ) ****************************************************************/ static int -cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk ) +cmp_seckey( PKT_public_key *req_pk, PKT_secret_key *sk ) { int n,i; - assert( req_sk->pubkey_algo == sk->pubkey_algo ); + if (req_pk->pubkey_algo != sk->pubkey_algo) + return -1; - n = pubkey_get_nskey( req_sk->pubkey_algo ); - for(i=0; i < n; i++ ) { - /* Note: becuase v4 protected keys have nothing in the - * mpis except for the first one, we skip all NULL MPIs. - * This might not be always correct in cases where the both - * keys do not match in their secret parts but we can ignore that - * because the need for this function is quite ugly. */ - if( req_sk->skey[1] && sk->skey[i] - && mpi_cmp( req_sk->skey[i], sk->skey[i] ) ) + n = pubkey_get_npkey (req_pk->pubkey_algo); + for (i=0; i < n; i++ ) { + if( mpi_cmp (req_pk->pkey[i], sk->skey[i]) ) return -1; } return 0; @@ -1104,16 +1003,15 @@ cmp_pubkey( PKT_public_key *req_pk, PKT_public_key *pk ) * search one keyring, return 0 if found, -1 if not found or an errorcode. */ static int -keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) +keyring_search( PKT_public_key *req_pk, u32 *req_keyid, + KBPOS *kbpos, IOBUF iobuf, const char *fname ) { int rc; PACKET pkt; int save_mode; - off_t offset; - int pkttype = req->pkttype; - PKT_public_key *req_pk = req->pkt.public_key; - PKT_secret_key *req_sk = req->pkt.secret_key; + off_t offset, main_offset; + assert (!!req_pk ^ !!req_keyid); /* exactly one must be specified */ init_packet(&pkt); save_mode = set_packet_list_mode(0); kbpos->rt = rt_RING; @@ -1135,29 +1033,57 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) } #endif - while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) { - if( pkt.pkttype == PKT_SECRET_KEY ) { + main_offset = 0; + while ( !(rc=search_packet(iobuf, &pkt, &offset)) ) { + if (pkt.pkttype == PKT_PUBLIC_KEY || pkt.pkttype == PKT_SECRET_KEY) { + main_offset = offset; + } + + if (pkt.pkttype == PKT_SECRET_KEY || pkt.pkttype == PKT_SECRET_SUBKEY) { PKT_secret_key *sk = pkt.pkt.secret_key; - if( req_sk->timestamp == sk->timestamp - && req_sk->pubkey_algo == sk->pubkey_algo - && !cmp_seckey( req_sk, sk) ) - break; /* found */ + if (req_keyid) { + u32 aki[2]; + + keyid_from_sk (sk, aki); + if (aki[0] == req_keyid[0] && aki[1] == req_keyid[1]) + break; /* found */ + } + else { + /* We can't compare the timestamps here because they + might differ */ + if( !cmp_seckey (req_pk, sk) ) + break; /* found */ + } } - else if( pkt.pkttype == PKT_PUBLIC_KEY ) { + else if (pkt.pkttype == PKT_PUBLIC_KEY + || pkt.pkttype == PKT_PUBLIC_SUBKEY) { PKT_public_key *pk = pkt.pkt.public_key; - if( req_pk->timestamp == pk->timestamp - && req_pk->pubkey_algo == pk->pubkey_algo - && !cmp_pubkey( req_pk, pk ) ) - break; /* found */ + if (req_keyid) { + u32 aki[2]; + + keyid_from_pk (pk, aki); + if (aki[0] == req_keyid[0] && aki[1] == req_keyid[1]) + break; /* found */ + } + else { + if( req_pk->timestamp == pk->timestamp + && req_pk->pubkey_algo == pk->pubkey_algo + && !cmp_pubkey( req_pk, pk ) ) + break; /* found */ + } } else BUG(); free_packet(&pkt); } if( !rc ) { - kbpos->offset = offset; + if (pkt.pkttype == PKT_SECRET_SUBKEY + || pkt.pkttype == PKT_PUBLIC_SUBKEY) + kbpos->offset = main_offset; + else + kbpos->offset = offset; kbpos->valid = 1; } @@ -1710,6 +1636,7 @@ do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, const byte *fpr, int fprlen ) * locate by keyid. * FIXME: we must have a way to enumerate thru the list opf fingerprints */ +#if 0 /* not used */ static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid ) { @@ -1752,7 +1679,7 @@ do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid ) free( content.dptr ); /* can't use m_free() here */ return rc; } - +#endif /* not used */ static int |