diff --git a/g10/export.c b/g10/export.c index b3ad69718..224847e0f 100644 --- a/g10/export.c +++ b/g10/export.c @@ -129,6 +129,8 @@ parse_export_options(char *str,unsigned int *options,int noisy) N_("export revocation keys marked as \"sensitive\"")}, {"export-clean",EXPORT_CLEAN,NULL, N_("remove unusable parts from key during export")}, + {"export-realclean",EXPORT_MINIMAL|EXPORT_REALCLEAN|EXPORT_CLEAN,NULL, + NULL}, {"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL, N_("remove as much as possible from key during export")}, @@ -166,7 +168,7 @@ parse_export_options(char *str,unsigned int *options,int noisy) { *options |= (EXPORT_LOCAL_SIGS | EXPORT_ATTRIBUTES | EXPORT_SENSITIVE_REVKEYS); - *options &= ~(EXPORT_CLEAN | EXPORT_MINIMAL + *options &= ~(EXPORT_CLEAN | EXPORT_MINIMAL | EXPORT_REALCLEAN | EXPORT_DANE_FORMAT); } @@ -643,7 +645,7 @@ canon_pk_algo (enum gcry_pk_algos algo) } -/* Take an s-expression wit the public and private key and change the +/* Take an s-expression with the public and private key and change the * parameter array in PK to include the secret parameters. */ static gpg_error_t secret_key_to_mode1003 (gcry_sexp_t s_key, PKT_public_key *pk) @@ -2366,8 +2368,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret, if ((options & EXPORT_CLEAN)) { merge_keys_and_selfsig (ctrl, keyblock); - clean_all_uids (ctrl, keyblock, opt.verbose, - (options&EXPORT_MINIMAL), NULL, NULL); + clean_all_uids (ctrl, keyblock, opt.verbose, options, NULL, NULL); clean_all_subkeys (ctrl, keyblock, opt.verbose, (options&EXPORT_MINIMAL)? KEY_CLEAN_ALL /**/ : KEY_CLEAN_AUTHENCR, diff --git a/g10/import.c b/g10/import.c index 8f874a7d1..ff8847cb6 100644 --- a/g10/import.c +++ b/g10/import.c @@ -2081,7 +2081,9 @@ import_one_real (ctrl_t ctrl, { merge_keys_and_selfsig (ctrl, keyblock); clean_all_uids (ctrl, keyblock, - opt.verbose, (options&IMPORT_MINIMAL), NULL, NULL); + opt.verbose, + (options&IMPORT_MINIMAL)? EXPORT_MINIMAL : 0, + NULL, NULL); clean_all_subkeys (ctrl, keyblock, opt.verbose, KEY_CLEAN_NONE, NULL, NULL); } @@ -2233,7 +2235,8 @@ import_one_real (ctrl_t ctrl, if ((options & IMPORT_CLEAN)) { merge_keys_and_selfsig (ctrl, keyblock); - clean_all_uids (ctrl, keyblock, opt.verbose, (options&IMPORT_MINIMAL), + clean_all_uids (ctrl, keyblock, opt.verbose, + (options&IMPORT_MINIMAL)? EXPORT_MINIMAL : 0, &n_uids_cleaned,&n_sigs_cleaned); clean_all_subkeys (ctrl, keyblock, opt.verbose, KEY_CLEAN_NONE, NULL, NULL); @@ -2331,7 +2334,7 @@ import_one_real (ctrl_t ctrl, { merge_keys_and_selfsig (ctrl, keyblock_orig); clean_all_uids (ctrl, keyblock_orig, opt.verbose, - (options&IMPORT_MINIMAL), + (options&IMPORT_MINIMAL)? EXPORT_MINIMAL : 0, &n_uids_cleaned,&n_sigs_cleaned); clean_all_subkeys (ctrl, keyblock_orig, opt.verbose, KEY_CLEAN_NONE, NULL, NULL); diff --git a/g10/key-clean.c b/g10/key-clean.c index c8a6efe50..ca8ca40d9 100644 --- a/g10/key-clean.c +++ b/g10/key-clean.c @@ -91,6 +91,7 @@ mark_usable_uid_certs (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode, continue; } node->flag |= 1<next) @@ -215,9 +216,22 @@ mark_usable_uid_certs (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode, } +/* Return true if the signature at NODE has is from a key specified by + * the --trusted-key option and is exportable. */ +static int +is_trusted_key_sig (kbnode_t node) +{ + if (!node->pkt->pkt.signature->flags.exportable) + return 0; + /* Not yet implemented. */ + return 0; +} + + +/* Note: OPTIONS are from the EXPORT_* set. */ static int clean_sigs_from_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode, - int noisy, int self_only) + int noisy, unsigned int options) { int deleted = 0; kbnode_t node; @@ -256,8 +270,15 @@ clean_sigs_from_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode, { int keep; - keep = self_only? (node->pkt->pkt.signature->keyid[0] == keyid[0] - && node->pkt->pkt.signature->keyid[1] == keyid[1]) : 1; + if ((options & EXPORT_REALCLEAN)) + keep = ((node->pkt->pkt.signature->keyid[0] == keyid[0] + && node->pkt->pkt.signature->keyid[1] == keyid[1]) + || is_trusted_key_sig (node)); + else if ((options & EXPORT_MINIMAL)) + keep = (node->pkt->pkt.signature->keyid[0] == keyid[0] + && node->pkt->pkt.signature->keyid[1] == keyid[1]); + else + keep = 1; /* Keep usable uid sigs ... */ if ((node->flag & (1<pkt->pkt.user_id->flags.compacted) *sigs_cleaned += clean_sigs_from_uid (ctrl, keyblock, uidnode, - noisy, self_only); + noisy, options); } /* NB: This function marks the deleted nodes only and the caller is * responsible to skip or remove them. Needs to be called after a - * merge_keys_and_selfsig(). */ + * merge_keys_and_selfsig. Note: OPTIONS are from the EXPORT_* set. */ void -clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, int self_only, +clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, unsigned int options, int *uids_cleaned, int *sigs_cleaned) { kbnode_t node; @@ -405,7 +428,7 @@ clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, int self_only, node = node->next) { if (node->pkt->pkttype == PKT_USER_ID) - clean_one_uid (ctrl, keyblock, node, noisy, self_only, + clean_one_uid (ctrl, keyblock, node, noisy, options, uids_cleaned, sigs_cleaned); } diff --git a/g10/key-clean.h b/g10/key-clean.h index c4f164928..b2825b0c5 100644 --- a/g10/key-clean.h +++ b/g10/key-clean.h @@ -40,9 +40,10 @@ void mark_usable_uid_certs (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode, u32 curtime, u32 *next_expire); void clean_one_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode, - int noisy, int self_only, + int noisy, unsigned int options, int *uids_cleaned, int *sigs_cleaned); -void clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, int self_only, +void clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, + int noisy, unsigned int options, int *uids_cleaned,int *sigs_cleaned); void clean_all_subkeys (ctrl_t ctrl, kbnode_t keyblock, int noisy, int clean_level, diff --git a/g10/keydb.h b/g10/keydb.h index 798c24da3..62a99295d 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -573,6 +573,7 @@ const char *colon_expirestr_from_sig (PKT_signature *sig); byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len ); byte *v5_fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len); void fpr20_from_pk (PKT_public_key *pk, byte array[20]); +void fpr20_from_fpr (const byte *fpr, unsigned int fprlen, byte array[20]); char *hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen); char *v5hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen); char *format_hexfingerprint (const char *fingerprint, diff --git a/g10/keyedit.c b/g10/keyedit.c index e56e6d10b..7523a1a62 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -70,7 +70,7 @@ static int menu_adduid (ctrl_t ctrl, kbnode_t keyblock, int photo, const char *photo_name, const char *uidstr); static void menu_deluid (KBNODE pub_keyblock); static int menu_delsig (ctrl_t ctrl, kbnode_t pub_keyblock); -static int menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only); +static int menu_clean (ctrl_t ctrl, kbnode_t keyblock, unsigned int options); static void menu_delkey (KBNODE pub_keyblock); static int menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive); static int menu_addadsk (ctrl_t ctrl, kbnode_t pub_keyblock, @@ -2258,7 +2258,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, break; case cmdMINIMIZE: - if (menu_clean (ctrl, keyblock, 1)) + if (menu_clean (ctrl, keyblock, EXPORT_MINIMAL)) redisplay = modified = 1; break; @@ -4543,11 +4543,13 @@ menu_delsig (ctrl_t ctrl, kbnode_t pub_keyblock) } +/* Note: OPTIONS are from the EXPORT_* set. */ static int -menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only) +menu_clean (ctrl_t ctrl, kbnode_t keyblock, unsigned int options) { KBNODE uidnode; - int modified = 0, select_all = !count_selected_uids (keyblock); + int modified = 0; + int select_all = !count_selected_uids (keyblock); for (uidnode = keyblock->next; uidnode && uidnode->pkt->pkttype != PKT_PUBLIC_SUBKEY; @@ -4561,8 +4563,8 @@ menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only) uidnode->pkt->pkt.user_id->len, 0); - clean_one_uid (ctrl, keyblock, uidnode, opt.verbose, self_only, &uids, - &sigs); + clean_one_uid (ctrl, keyblock, uidnode, opt.verbose, options, + &uids, &sigs); if (uids) { const char *reason; @@ -4587,7 +4589,7 @@ menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only) } else { - tty_printf (self_only == 1 ? + tty_printf ((options & EXPORT_MINIMAL)? _("User ID \"%s\": already minimized\n") : _("User ID \"%s\": already clean\n"), user); } diff --git a/g10/keyid.c b/g10/keyid.c index ce977de0b..fab1e3a36 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -1050,6 +1050,32 @@ v5_fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len) } +/* + * This is the core of fpr20_from_pk which directly takes a + * fingerprint and its length instead of the public key. See below + * for details. + */ +void +fpr20_from_fpr (const byte *fpr, unsigned int fprlen, byte array[20]) +{ + if (fprlen >= 32) /* v5 fingerprint (or larger) */ + { + memcpy (array + 0, fpr + 20, 4); + memcpy (array + 4, fpr + 24, 4); + memcpy (array + 8, fpr + 28, 4); + memcpy (array + 12, fpr + 0, 4); /* kid[0] */ + memcpy (array + 16, fpr + 4, 4); /* kid[1] */ + } + else if (fprlen == 20) /* v4 fingerprint */ + memcpy (array, fpr, 20); + else /* v3 or too short: fill up with zeroes. */ + { + memset (array, 0, 20); + memcpy (array, fpr, fprlen); + } +} + + /* * Get FPR20 for the given PK/SK into ARRAY. * @@ -1066,19 +1092,7 @@ fpr20_from_pk (PKT_public_key *pk, byte array[20]) if (!pk->fprlen) compute_fingerprint (pk); - if (!array) - array = xmalloc (pk->fprlen); - - if (pk->fprlen == 32) /* v5 fingerprint */ - { - memcpy (array + 0, pk->fpr + 20, 4); - memcpy (array + 4, pk->fpr + 24, 4); - memcpy (array + 8, pk->fpr + 28, 4); - memcpy (array + 12, pk->fpr + 0, 4); /* kid[0] */ - memcpy (array + 16, pk->fpr + 4, 4); /* kid[1] */ - } - else /* v4 fingerprint */ - memcpy (array, pk->fpr, 20); + fpr20_from_fpr (pk->fpr, pk->fprlen, array); } diff --git a/g10/options.h b/g10/options.h index 07516aab1..458180c7a 100644 --- a/g10/options.h +++ b/g10/options.h @@ -416,12 +416,13 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode; #define EXPORT_ATTRIBUTES (1<<1) #define EXPORT_SENSITIVE_REVKEYS (1<<2) #define EXPORT_RESET_SUBKEY_PASSWD (1<<3) -#define EXPORT_MINIMAL (1<<4) -#define EXPORT_CLEAN (1<<5) +#define EXPORT_MINIMAL (1<<5) +#define EXPORT_CLEAN (1<<6) #define EXPORT_DANE_FORMAT (1<<7) #define EXPORT_BACKUP (1<<10) #define EXPORT_REVOCS (1<<11) #define EXPORT_MODE1003 (1<<12) +#define EXPORT_REALCLEAN (1<<13) #define LIST_SHOW_PHOTOS (1<<0) #define LIST_SHOW_POLICY_URLS (1<<1) diff --git a/g10/tdbdump.c b/g10/tdbdump.c index 2a02ad108..058ab5cf6 100644 --- a/g10/tdbdump.c +++ b/g10/tdbdump.c @@ -193,7 +193,11 @@ import_ownertrust (ctrl_t ctrl, const char *fname ) while (fprlen < MAX_FINGERPRINT_LEN) fpr[fprlen++] = 0; - rc = tdbio_search_trust_byfpr (ctrl, fpr, &rec); + /* FIXME: The intention is to save the special fpr20 as used + * in the trustdb here. However, the above conversions seems + * not to be aware of this. Or why does it allow up to + * MAX_FINGERPRINT_LEN ? */ + rc = tdbio_search_trust_byfpr (ctrl, fpr, 20, &rec); if( !rc ) { /* found: update */ if (rec.r.trust.ownertrust != otrust) { diff --git a/g10/tdbio.c b/g10/tdbio.c index 1b68f772f..7ee62fca0 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -1864,13 +1864,21 @@ cmp_trec_fpr ( const void *fpr, const TRUSTREC *rec ) * Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code. */ gpg_error_t -tdbio_search_trust_byfpr (ctrl_t ctrl, const byte *fingerprint, TRUSTREC *rec) +tdbio_search_trust_byfpr (ctrl_t ctrl, const byte *fpr, unsigned int fprlen, + TRUSTREC *rec) { int rc; + byte fingerprint[20]; + + if (fprlen != 20) + { + fpr20_from_fpr (fpr, fprlen, fingerprint); + fpr = fingerprint; + } /* Locate the trust record using the hash table */ - rc = lookup_hashtable (get_trusthashrec (ctrl), fingerprint, 20, - cmp_trec_fpr, fingerprint, rec ); + rc = lookup_hashtable (get_trusthashrec (ctrl), fpr, 20, + cmp_trec_fpr, fpr, rec); return rc; } @@ -1887,7 +1895,7 @@ tdbio_search_trust_bypk (ctrl_t ctrl, PKT_public_key *pk, TRUSTREC *rec) byte fingerprint[20]; fpr20_from_pk (pk, fingerprint); - return tdbio_search_trust_byfpr (ctrl, fingerprint, rec); + return tdbio_search_trust_byfpr (ctrl, fingerprint, 20, rec); } diff --git a/g10/tdbio.h b/g10/tdbio.h index 9452d76c9..7cf630121 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -111,7 +111,8 @@ int tdbio_end_transaction(void); int tdbio_cancel_transaction(void); int tdbio_delete_record (ctrl_t ctrl, ulong recnum); ulong tdbio_new_recnum (ctrl_t ctrl); -gpg_error_t tdbio_search_trust_byfpr (ctrl_t ctrl, const byte *fingerprint, +gpg_error_t tdbio_search_trust_byfpr (ctrl_t ctrl, + const byte *fpr, unsigned int fprlen, TRUSTREC *rec); gpg_error_t tdbio_search_trust_bypk (ctrl_t ctrl, PKT_public_key *pk, TRUSTREC *rec);