diff --git a/doc/gpg.texi b/doc/gpg.texi index 4fdff42e4..8189ae8ac 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -888,6 +888,13 @@ Signs a public key with your secret key but marks it as non-exportable. This is a shortcut version of the subcommand "lsign" from @option{--edit-key}. +@ifclear gpgone +@item --passwd @var{user_id} +@opindex passwd +Change the passphrase of the secret key belonging to the certificate +specified as @var{user_id}. This is a shortcut for the sub-command +@code{passwd} of the edit key menu. +@end ifclear @end table diff --git a/g10/ChangeLog b/g10/ChangeLog index 986b02dbe..1058c576e 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,53 @@ +2010-02-02 Werner Koch + + * keyedit.c (keyedit_menu): Change prompt to "gpg". + * card-util.c (card_edit): Change prompt to "gpg/card". + +2010-01-11 Werner Koch + + * sign.c (only_old_style, write_onepass_sig_packets, hash_for) + (write_signature_packets, print_status_sig_created) + (clearsign_file, make_keysig_packet, mk_notation_policy_etc) + (complete_sig, do_sign, update_keysig_packet): Replace all + secret key access by the matching public key. + * keylist.c (print_seckey_info): Ditto. + * revoke.c (gen_desig_revoke): Ditto. + * skclist.c (release_sk_list): Ditto. + * keyedit.c (sign_uids): Ditto. + * misc.c (get_signature_count): Ditto. + * main.h (struct expand_args): s/sk/pksk/. Change all users. + + * keyedit.c (keyedit_passwd): Finish implementation. + +2010-01-10 Werner Koch + + * skclist.c (GCRYCTL_FAKED_RANDOM_P): Remove because we require + libgcrypt 1.4. + (is_insecure, key_present_in_sk_list): Work with public keys. + (build_sk_list): Change to work on public keys. + * keydb.h (struct sk_list): Replace field SK by a PK field. + + * keylist.c (list_keyblock_print): Always look for the public key + and ignore all secret key packets. + (list_keyblock_colon): Ditto. + (print_capabilities): Remove arg SK and all secret key stuff. + Adjust all callers. + (dump_attribs): Ditto. + + * getkey.c (getkey_bynames, getkey_next, get_pubkey_end): New. + (getkey_byname): New. + (getkey_ctx_s): Add WANT_SECRET. + (key_byname): Set it. + (merge_keys_and_selfsig): Remove all the secret key merging. + (lookup): Simplify by removing secret key code. + + * keylist.c (list_all): Scan public keys and use have_secret_key + to filter secret keys. + (list_one): Use the new get_key functions. + + * gpg.h (kbnode_t): Add as alias for KBNODE. + * keydb.h (getkey_ctx_t): Add as alias for GETKEY_CTX. + 2010-01-09 Werner Koch * getkey.c, keylist.c: Re-indent. diff --git a/g10/card-util.c b/g10/card-util.c index 96a994c98..9bd5013a1 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -1817,7 +1817,7 @@ card_edit (strlist_t commands) if (!have_commands) { tty_enable_completion (card_edit_completion); - answer = cpr_get_no_help("cardedit.prompt", _("Command> ")); + answer = cpr_get_no_help("cardedit.prompt", _("gpg/card> ")); cpr_kill_prompt(); tty_disable_completion (); } diff --git a/g10/free-packet.c b/g10/free-packet.c index 85f23ce3f..5da7fc0ac 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -471,6 +471,7 @@ cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b ) { int n, i; + log_debug ("FIXME: %s Should not be used\n", __func__); if( a->timestamp != b->timestamp ) return -1; if( a->version < 4 && a->expiredate != b->expiredate ) diff --git a/g10/getkey.c b/g10/getkey.c index 96537b7d3..b5db65da0 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -46,6 +46,7 @@ struct getkey_ctx_s { int exact; + int want_secret; /* The caller requested only secret keys. */ KBNODE keyblock; KBPOS kbpos; KBNODE found_key; /* Pointer into some keyblock. */ @@ -101,8 +102,8 @@ typedef struct user_id_db static user_id_db_t user_id_db; static int uid_cache_entries; /* Number of entries in uid cache. */ -static void merge_selfsigs (KBNODE keyblock); -static int lookup (GETKEY_CTX ctx, KBNODE * ret_keyblock, int secmode); +static void merge_selfsigs (kbnode_t keyblock); +static int lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret); #if 0 static void @@ -599,7 +600,7 @@ leave: /* Try to get the pubkey by the userid. This function looks for the - * first pubkey certificate which has the given name in a user_id. if + * first pubkey certificate which has the given name in a user_id. If * pk/sk has the pubkey algo set, the function will only return a * pubkey with that algo. If namelist is NULL, the first key is * returned. The caller should provide storage for either the pk or @@ -608,7 +609,7 @@ leave: static int key_byname (GETKEY_CTX * retctx, strlist_t namelist, PKT_public_key * pk, PKT_secret_key * sk, - int secmode, int include_unusable, + int want_secret, int include_unusable, KBNODE * ret_kb, KEYDB_HANDLE * ret_kdbhd) { int rc = 0; @@ -617,6 +618,8 @@ key_byname (GETKEY_CTX * retctx, strlist_t namelist, GETKEY_CTX ctx; KBNODE help_kb = NULL; + /* FIXME: Eventually remove the SK argument. */ + if (retctx) { /* Reset the returned context in case of error. */ @@ -667,35 +670,25 @@ key_byname (GETKEY_CTX * retctx, strlist_t namelist, } } - ctx->kr_handle = keydb_new (secmode); + ctx->want_secret = want_secret; + ctx->kr_handle = keydb_new (0); if (!ret_kb) ret_kb = &help_kb; - if (secmode) + if (pk) { - if (sk) - { - ctx->req_algo = sk->req_algo; - ctx->req_usage = sk->req_usage; - } - rc = lookup (ctx, ret_kb, 1); - if (!rc && sk) - { - sk_from_block (ctx, sk, *ret_kb); - } + ctx->req_algo = pk->req_algo; + ctx->req_usage = pk->req_usage; } - else + else if (sk) /* FIXME: We should remove this. */ { - if (pk) - { - ctx->req_algo = pk->req_algo; - ctx->req_usage = pk->req_usage; - } - rc = lookup (ctx, ret_kb, 0); - if (!rc && pk) - { - pk_from_block (ctx, pk, *ret_kb); - } + ctx->req_algo = sk->req_algo; + ctx->req_usage = sk->req_usage; + } + rc = lookup (ctx, ret_kb, want_secret); + if (!rc && pk) + { + pk_from_block (ctx, pk, *ret_kb); } release_kbnode (help_kb); @@ -1219,115 +1212,102 @@ get_seckeyblock_byfprint (KBNODE * ret_keyblock, const byte * fprint, return rc; } + + +/* The new function to return a key. + FIXME: Document it. */ +gpg_error_t +getkey_bynames (getkey_ctx_t *retctx, PKT_public_key *pk, + strlist_t names, int want_secret, kbnode_t *ret_keyblock) +{ + return key_byname (retctx, names, pk, NULL, want_secret, 1, + ret_keyblock, NULL); +} + + +/* Get a key by name and store it into PK. If RETCTX is not NULL + * return the search context which needs to be released by the caller + * using getkey_end. If NAME is NULL use the default key (see below). + * On success and if RET_KEYBLOCK is not NULL the found keyblock is + * stored at this address. WANT_SECRET passed as true requires that a + * secret key is available for the selected key. + * + * If WANT_SECRET is true and NAME is NULL and a default key has been + * defined that defined key is used. In all other cases the first + * available key is used. + * + * FIXME: Explain what is up with unusable keys. + * + * FIXME: We also have the get_pubkey_byname fucntion which has a + * different semantic. Should be merged with this one. + */ +gpg_error_t +getkey_byname (getkey_ctx_t *retctx, PKT_public_key *pk, + const char *name, int want_secret, kbnode_t *ret_keyblock) +{ + gpg_error_t err; + strlist_t namelist = NULL; + int with_unusable = 1; + + if (want_secret && !name && opt.def_secret_key && *opt.def_secret_key) + add_to_strlist (&namelist, opt.def_secret_key); + else if (name) + add_to_strlist (&namelist, name); + else + with_unusable = 0; + + err = key_byname (retctx, namelist, pk, NULL, want_secret, with_unusable, + ret_keyblock, NULL); + + /* FIXME: Check that we really return GPG_ERR_NO_SECKEY if + WANT_SECRET has been used. */ + + free_strlist (namelist); + + return err; +} + + +/* The new function to return the next key. */ +gpg_error_t +getkey_next (getkey_ctx_t ctx, PKT_public_key *pk, kbnode_t *ret_keyblock) +{ + int rc; /* Fixme: Make sure this is proper gpg_error */ + + rc = lookup (ctx, ret_keyblock, ctx->want_secret); + if (!rc && pk && ret_keyblock) + pk_from_block (ctx, pk, *ret_keyblock); + + return rc; +} + + +/* The new function to finish a key listing. */ +void +getkey_end (getkey_ctx_t ctx) +{ + get_pubkey_end (ctx); +} + + /************************************************ ************* Merging stuff ******************** ************************************************/ -/* Merge all self-signatures with the keys. - - * FIXME: replace this at least for the public key parts - * by merge_selfsigs. - * It is still used in keyedit.c and - * at 2 or 3 other places - check whether it is really needed. - * It might be needed by the key edit and import stuff because - * the keylock is changed. */ +/* Merge all self-signatures with the keys. */ void merge_keys_and_selfsig (KBNODE keyblock) { - PKT_public_key *pk = NULL; - PKT_secret_key *sk = NULL; - PKT_signature *sig; - KBNODE k; - u32 kid[2] = { 0, 0 }; - u32 sigdate = 0; - - if (keyblock && keyblock->pkt->pkttype == PKT_PUBLIC_KEY) - { - /* Divert to our new function. */ - merge_selfsigs (keyblock); - return; - } - - /* Still need the old one because the new one can't handle secret keys. */ - - for (k = keyblock; k; k = k->next) - { - if (k->pkt->pkttype == PKT_PUBLIC_KEY - || k->pkt->pkttype == PKT_PUBLIC_SUBKEY) - { - pk = k->pkt->pkt.public_key; - sk = NULL; - if (pk->version < 4) - pk = NULL; /* Not needed for old keys. */ - else if (k->pkt->pkttype == PKT_PUBLIC_KEY) - keyid_from_pk (pk, kid); - else if (!pk->expiredate) - { - /* and subkey */ - /* insert the expiration date here */ - /*FIXME!!! pk->expiredate = subkeys_expiretime( k, kid ); */ - } - sigdate = 0; - } - else if (k->pkt->pkttype == PKT_SECRET_KEY - || k->pkt->pkttype == PKT_SECRET_SUBKEY) - { - pk = NULL; - sk = k->pkt->pkt.secret_key; - if (sk->version < 4) - sk = NULL; - else if (k->pkt->pkttype == PKT_SECRET_KEY) - keyid_from_sk (sk, kid); - sigdate = 0; - } - else if ((pk || sk) && k->pkt->pkttype == PKT_SIGNATURE - && (sig = k->pkt->pkt.signature)->sig_class >= 0x10 - && sig->sig_class <= 0x30 && sig->version > 3 - && !(sig->sig_class == 0x18 || sig->sig_class == 0x28) - && sig->keyid[0] == kid[0] && sig->keyid[1] == kid[1]) - { - /* okay this is a self-signature which can be used. - * This is not used for subkey binding signature, becuase this - * is done above. - * FIXME: We should only use this if the signature is valid - * but this is time consuming - we must provide another - * way to handle this - */ - const byte *p; - u32 ed; - - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); - if (pk) - { - ed = p ? pk->timestamp + buffer_to_u32 (p) : 0; - if (sig->timestamp > sigdate) - { - pk->expiredate = ed; - sigdate = sig->timestamp; - } - } - else - { - ed = p ? sk->timestamp + buffer_to_u32 (p) : 0; - if (sig->timestamp > sigdate) - { - sk->expiredate = ed; - sigdate = sig->timestamp; - } - } - } - - if (pk && (pk->expiredate == 0 || - (pk->max_expiredate && pk->expiredate > pk->max_expiredate))) - pk->expiredate = pk->max_expiredate; - - if (sk && (sk->expiredate == 0 || - (sk->max_expiredate && sk->expiredate > sk->max_expiredate))) - sk->expiredate = sk->max_expiredate; - } + if (!keyblock) + ; + else if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY) + merge_selfsigs (keyblock); + else + log_debug ("FIXME: merging secret key blocks is not anymore available\n"); } + static int parse_key_usage (PKT_signature * sig) { @@ -2309,146 +2289,10 @@ merge_selfsigs (KBNODE keyblock) } -/* - * Merge the secret keys from secblock into the pubblock thereby - * replacing the public (sub)keys with their secret counterparts Hmmm: - * It might be better to get away from the concept of entire secret - * keys at all and have a way to store just the real secret parts - * from the key. - */ -static void -merge_public_with_secret (KBNODE pubblock, KBNODE secblock) -{ - KBNODE pub; - - assert (pubblock->pkt->pkttype == PKT_PUBLIC_KEY); - assert (secblock->pkt->pkttype == PKT_SECRET_KEY); - - for (pub = pubblock; pub; pub = pub->next) - { - if (pub->pkt->pkttype == PKT_PUBLIC_KEY) - { - PKT_public_key *pk = pub->pkt->pkt.public_key; - PKT_secret_key *sk = secblock->pkt->pkt.secret_key; - assert (pub == pubblock); /* Only in the first node. */ - /* There is nothing to compare in this case, so just replace - * some information. */ - copy_public_parts_to_secret_key (pk, sk); - free_public_key (pk); - pub->pkt->pkttype = PKT_SECRET_KEY; - pub->pkt->pkt.secret_key = copy_secret_key (NULL, sk); - } - else if (pub->pkt->pkttype == PKT_PUBLIC_SUBKEY) - { - KBNODE sec; - PKT_public_key *pk = pub->pkt->pkt.public_key; - - /* This is more complicated: It may happen that the sequence - * of the subkeys dosn't match, so we have to find the - * appropriate secret key. */ - for (sec = secblock->next; sec; sec = sec->next) - { - if (sec->pkt->pkttype == PKT_SECRET_SUBKEY) - { - PKT_secret_key *sk = sec->pkt->pkt.secret_key; - if (!cmp_public_secret_key (pk, sk)) - { - copy_public_parts_to_secret_key (pk, sk); - free_public_key (pk); - pub->pkt->pkttype = PKT_SECRET_SUBKEY; - pub->pkt->pkt.secret_key = copy_secret_key (NULL, sk); - break; - } - } - } - if (!sec) - BUG (); /* Already checked in premerge. */ - } - } -} - - -/* This function checks that for every public subkey a corresponding - * secret subkey is available and deletes the public subkey otherwise. - * We need this function because we can't delete it later when we - * actually merge the secret parts into the pubring. - * The function also plays some games with the node flags. */ -static void -premerge_public_with_secret (KBNODE pubblock, KBNODE secblock) -{ - KBNODE last, pub; - - assert (pubblock->pkt->pkttype == PKT_PUBLIC_KEY); - assert (secblock->pkt->pkttype == PKT_SECRET_KEY); - - for (pub = pubblock, last = NULL; pub; last = pub, pub = pub->next) - { - pub->flag &= ~3; /* Reset bits 0 and 1. */ - if (pub->pkt->pkttype == PKT_PUBLIC_SUBKEY) - { - KBNODE sec; - PKT_public_key *pk = pub->pkt->pkt.public_key; - - for (sec = secblock->next; sec; sec = sec->next) - { - if (sec->pkt->pkttype == PKT_SECRET_SUBKEY) - { - PKT_secret_key *sk = sec->pkt->pkt.secret_key; - if (!cmp_public_secret_key (pk, sk)) - { - if (sk->protect.s2k.mode == 1001) - { - /* The secret parts are not available so - we can't use that key for signing etc. - Fix the pubkey usage */ - pk->pubkey_usage &= ~(PUBKEY_USAGE_SIG - | PUBKEY_USAGE_AUTH); - } - /* Transfer flag bits 0 and 1 to the pubblock. */ - pub->flag |= (sec->flag & 3); - break; - } - } - } - if (!sec) - { - KBNODE next, ll; - - if (opt.verbose) - log_info (_("no secret subkey" - " for public subkey %s - ignoring\n"), - keystr_from_pk (pk)); - /* We have to remove the subkey in this case. */ - assert (last); - /* Find the next subkey. */ - for (next = pub->next, ll = pub; - next && next->pkt->pkttype != PKT_PUBLIC_SUBKEY; - ll = next, next = next->next) - ; - /* Make new link. */ - last->next = next; - /* Release this public subkey with all sigs. */ - ll->next = NULL; - release_kbnode (pub); - /* Let the loop continue. */ - pub = last; - } - } - } - /* We need to copy the found bits (0 and 1) from the secret key to - the public key. This has already been done for the subkeys but - got lost on the primary key - fix it here. */ - pubblock->flag |= (secblock->flag & 3); -} - - -/* See see whether the key fits our requirements and in case we do not - * request the primary key, we should select a suitable subkey. +/* See whether the key fits our requirements and in case we do not + * request the primary key, select a suitable subkey. * - * FIXME: Check against PGP 7 whether we still need a kludge - * to favor type 16 keys over type 20 keys when type 20 - * has not been explitely requested. * Returns: True when a suitable key has been found. * * We have to distinguish four cases: FIXME! @@ -2533,7 +2377,7 @@ finish_lookup (GETKEY_CTX ctx) if ((!foundk || foundk->pkt->pkttype == PKT_PUBLIC_SUBKEY) && !req_prim) { KBNODE nextk; - /* ceither start a loop or check just this one subkey. */ + /* Either start a loop or check just this one subkey. */ for (k = foundk ? foundk : keyblock; k; k = nextk) { PKT_public_key *pk; @@ -2635,7 +2479,7 @@ finish_lookup (GETKEY_CTX ctx) { if (DBG_CACHE) log_debug ("\tno suitable key found - giving up\n"); - return 0; + return 0; /* Not found. */ } found: @@ -2668,11 +2512,13 @@ found: } +/* The main function to lookup a key. On success the found keyblock + is stored at RET_KEYBLOCK and also in CTX. If WANT_SECRET is true + a corresponding secret key is required. */ static int -lookup (GETKEY_CTX ctx, KBNODE * ret_keyblock, int secmode) +lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret) { int rc; - KBNODE secblock = NULL; /* Helper. */ int no_suitable_key = 0; rc = 0; @@ -2692,30 +2538,8 @@ lookup (GETKEY_CTX ctx, KBNODE * ret_keyblock, int secmode) goto skip; } - if (secmode) - { - /* Find the correspondig public key and use this - * this one for the selection process. */ - u32 aki[2]; - KBNODE k = ctx->keyblock; - - if (k->pkt->pkttype != PKT_SECRET_KEY) - BUG (); - - keyid_from_sk (k->pkt->pkt.secret_key, aki); - k = get_pubkeyblock (aki); - if (!k) - { - if (!opt.quiet) - log_info (_("key %s: secret key without public key" - " - skipped\n"), keystr (aki)); - goto skip; - } - secblock = ctx->keyblock; - ctx->keyblock = k; - - premerge_public_with_secret (ctx->keyblock, secblock); - } + if (want_secret && have_secret_key (ctx->keyblock)) + goto skip; /* No secret key available. */ /* Warning: node flag bits 0 and 1 should be preserved by * merge_selfsigs. For secret keys, premerge did tranfer the @@ -2724,12 +2548,6 @@ lookup (GETKEY_CTX ctx, KBNODE * ret_keyblock, int secmode) if (finish_lookup (ctx)) { no_suitable_key = 0; - if (secmode) - { - merge_public_with_secret (ctx->keyblock, secblock); - release_kbnode (secblock); - secblock = NULL; - } goto found; } else @@ -2737,15 +2555,10 @@ lookup (GETKEY_CTX ctx, KBNODE * ret_keyblock, int secmode) skip: /* Release resources and continue search. */ - if (secmode) - { - release_kbnode (secblock); - secblock = NULL; - } release_kbnode (ctx->keyblock); ctx->keyblock = NULL; } - + found: if (rc && rc != -1) log_error ("keydb_search failed: %s\n", g10_errstr (rc)); @@ -2756,15 +2569,10 @@ found: ctx->keyblock = NULL; } else if (rc == -1 && no_suitable_key) - rc = secmode ? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY; + rc = want_secret? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY; else if (rc == -1) - rc = secmode ? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY; + rc = want_secret? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY; - if (secmode) - { - release_kbnode (secblock); - secblock = NULL; - } release_kbnode (ctx->keyblock); ctx->keyblock = NULL; @@ -3083,3 +2891,180 @@ parse_auto_key_locate (char *options) return 1; } + + +/* Return 0 if a secret key is available for the key described by + KEYBLOCK. FIXME: How do we handel subkeys? */ +gpg_error_t +have_secret_key (kbnode_t keyblock) +{ + gpg_error_t err; + unsigned char fpr[MAX_FINGERPRINT_LEN]; + size_t fprlen; + KEYDB_HANDLE kdh; + + if (!keyblock || keyblock->pkt->pkttype != PKT_PUBLIC_KEY) + return gpg_error (GPG_ERR_NO_PUBKEY); /* Should not happen. */ + + fingerprint_from_pk (keyblock->pkt->pkt.public_key, fpr, &fprlen); + while (fprlen < MAX_FINGERPRINT_LEN) + fpr[fprlen++] = 0; + + /* FIXME: Always allocating a new handle is too slow. However this + entire implementation is anyway a temporary solution until we can + ask gpg-agent for the secret key. */ + kdh = keydb_new (1); + if (!kdh) + return gpg_error (GPG_ERR_GENERAL); + + err = keydb_search_fpr (kdh, fpr); + if (err == -1 || gpg_err_code (err) == GPG_ERR_EOF) + err = gpg_error (GPG_ERR_NO_SECKEY); + + keydb_release (kdh); + + return err; +} + + + +#if 0 +/* + * Merge the secret keys from secblock into the pubblock thereby + * replacing the public (sub)keys with their secret counterparts Hmmm: + * It might be better to get away from the concept of entire secret + * keys at all and have a way to store just the real secret parts + * from the key. + * + * FIXME: this is not anymore needed but we keep it as example code for the + * new code we need to write for the import/export feature. + */ +static void +merge_public_with_secret (KBNODE pubblock, KBNODE secblock) +{ + KBNODE pub; + + assert (pubblock->pkt->pkttype == PKT_PUBLIC_KEY); + assert (secblock->pkt->pkttype == PKT_SECRET_KEY); + + for (pub = pubblock; pub; pub = pub->next) + { + if (pub->pkt->pkttype == PKT_PUBLIC_KEY) + { + PKT_public_key *pk = pub->pkt->pkt.public_key; + PKT_secret_key *sk = secblock->pkt->pkt.secret_key; + assert (pub == pubblock); /* Only in the first node. */ + /* There is nothing to compare in this case, so just replace + * some information. */ + copy_public_parts_to_secret_key (pk, sk); + free_public_key (pk); + pub->pkt->pkttype = PKT_SECRET_KEY; + pub->pkt->pkt.secret_key = copy_secret_key (NULL, sk); + } + else if (pub->pkt->pkttype == PKT_PUBLIC_SUBKEY) + { + KBNODE sec; + PKT_public_key *pk = pub->pkt->pkt.public_key; + + /* This is more complicated: It may happen that the sequence + * of the subkeys dosn't match, so we have to find the + * appropriate secret key. */ + for (sec = secblock->next; sec; sec = sec->next) + { + if (sec->pkt->pkttype == PKT_SECRET_SUBKEY) + { + PKT_secret_key *sk = sec->pkt->pkt.secret_key; + if (!cmp_public_secret_key (pk, sk)) + { + copy_public_parts_to_secret_key (pk, sk); + free_public_key (pk); + pub->pkt->pkttype = PKT_SECRET_SUBKEY; + pub->pkt->pkt.secret_key = copy_secret_key (NULL, sk); + break; + } + } + } + if (!sec) + BUG (); /* Already checked in premerge. */ + } + } +} + + +/* This function checks that for every public subkey a corresponding + * secret subkey is available and deletes the public subkey otherwise. + * We need this function because we can't delete it later when we + * actually merge the secret parts into the pubring. + * The function also plays some games with the node flags. + * + * FIXME: this is not anymore needed but we keep it as example code for the + * new code we need to write for the import/export feature. + */ +static void +premerge_public_with_secret (KBNODE pubblock, KBNODE secblock) +{ + KBNODE last, pub; + + assert (pubblock->pkt->pkttype == PKT_PUBLIC_KEY); + assert (secblock->pkt->pkttype == PKT_SECRET_KEY); + + for (pub = pubblock, last = NULL; pub; last = pub, pub = pub->next) + { + pub->flag &= ~3; /* Reset bits 0 and 1. */ + if (pub->pkt->pkttype == PKT_PUBLIC_SUBKEY) + { + KBNODE sec; + PKT_public_key *pk = pub->pkt->pkt.public_key; + + for (sec = secblock->next; sec; sec = sec->next) + { + if (sec->pkt->pkttype == PKT_SECRET_SUBKEY) + { + PKT_secret_key *sk = sec->pkt->pkt.secret_key; + if (!cmp_public_secret_key (pk, sk)) + { + if (sk->protect.s2k.mode == 1001) + { + /* The secret parts are not available so + we can't use that key for signing etc. + Fix the pubkey usage */ + pk->pubkey_usage &= ~(PUBKEY_USAGE_SIG + | PUBKEY_USAGE_AUTH); + } + /* Transfer flag bits 0 and 1 to the pubblock. */ + pub->flag |= (sec->flag & 3); + break; + } + } + } + if (!sec) + { + KBNODE next, ll; + + if (opt.verbose) + log_info (_("no secret subkey" + " for public subkey %s - ignoring\n"), + keystr_from_pk (pk)); + /* We have to remove the subkey in this case. */ + assert (last); + /* Find the next subkey. */ + for (next = pub->next, ll = pub; + next && next->pkt->pkttype != PKT_PUBLIC_SUBKEY; + ll = next, next = next->next) + ; + /* Make new link. */ + last->next = next; + /* Release this public subkey with all sigs. */ + ll->next = NULL; + release_kbnode (pub); + /* Let the loop continue. */ + pub = last; + } + } + } + /* We need to copy the found bits (0 and 1) from the secret key to + the public key. This has already been done for the subkeys but + got lost on the primary key - fix it here. */ + pubblock->flag |= (secblock->flag & 3); +} +#endif /*0*/ diff --git a/g10/gpg.h b/g10/gpg.h index da2a738dc..013b135b2 100644 --- a/g10/gpg.h +++ b/g10/gpg.h @@ -1,5 +1,5 @@ /* gpg.h - top level include file for gpg etc. - * Copyright (C) 2003, 2006 Free Software Foundation, Inc. + * Copyright (C) 2003, 2006, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -50,6 +50,7 @@ struct server_local_s; /* Object used to describe a keyblok node. */ typedef struct kbnode_struct *KBNODE; +typedef struct kbnode_struct *kbnode_t; /* Session control object. This object is passed to most functions to diff --git a/g10/keydb.c b/g10/keydb.c index 4236a5f94..41b8c1d33 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -353,8 +353,6 @@ keydb_new (int secret) KEYDB_HANDLE hd; int i, j; - if (secret) - log_debug ("FIXME: keydb_new called for secret keys\n"); hd = xmalloc_clear (sizeof *hd); hd->found = -1; diff --git a/g10/keydb.h b/g10/keydb.h index bd511c551..cb0e04087 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -1,6 +1,6 @@ /* keydb.h - Key database * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006 Free Software Foundation, Inc. + * 2006, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -40,6 +40,7 @@ struct getkey_ctx_s; typedef struct getkey_ctx_s *GETKEY_CTX; +typedef struct getkey_ctx_s *getkey_ctx_t; /**************** * A Keyblock is all packets which form an entire certificate; @@ -93,12 +94,13 @@ struct pk_list int flags; /* flag bit 1==throw_keyid */ }; -/* structure to hold a couple of secret key certificates */ +/* Structure to hold a list of secret key certificates. */ typedef struct sk_list *SK_LIST; -struct sk_list { - SK_LIST next; - PKT_secret_key *sk; - int mark; /* not used */ +struct sk_list +{ + SK_LIST next; + PKT_public_key *pk; + int mark; /* not used */ }; /* structure to collect all information which can be used to @@ -169,8 +171,8 @@ void warn_missing_aes_from_pklist (PK_LIST pk_list); /*-- skclist.c --*/ int random_is_faked (void); void release_sk_list( SK_LIST sk_list ); -int build_sk_list( strlist_t locusr, SK_LIST *ret_sk_list, - int unlock, unsigned use ); +gpg_error_t build_sk_list (strlist_t locusr, SK_LIST *ret_sk_list, + int unlock, unsigned use); /*-- passphrase.h --*/ unsigned char encode_s2k_iterations (int iterations); @@ -226,6 +228,18 @@ int get_seckey_byfprint( PKT_secret_key *sk, int get_seckeyblock_byfprint (KBNODE *ret_keyblock, const byte *fprint, size_t fprint_len ); +gpg_error_t getkey_bynames (getkey_ctx_t *retctx, PKT_public_key *pk, + strlist_t names, int want_secret, + kbnode_t *ret_keyblock); +gpg_error_t getkey_byname (getkey_ctx_t *retctx, PKT_public_key *pk, + const char *name, int want_secret, + kbnode_t *ret_keyblock); +gpg_error_t getkey_next (getkey_ctx_t ctx, PKT_public_key *pk, + kbnode_t *ret_keyblock); +void getkey_end (getkey_ctx_t ctx); + +gpg_error_t have_secret_key (kbnode_t keyblock); + int enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys, int with_spm ); diff --git a/g10/keyedit.c b/g10/keyedit.c index a9617f377..72f9c0268 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -511,7 +511,7 @@ sign_uids( KBNODE keyblock, strlist_t locusr, int *ret_modified, int rc = 0; SK_LIST sk_list = NULL; SK_LIST sk_rover = NULL; - PKT_secret_key *sk = NULL; + PKT_public_key *pk = NULL; KBNODE node, uidnode; PKT_public_key *primary_pk=NULL; int select_all = !count_selected_uids(keyblock) || interactive; @@ -550,14 +550,16 @@ sign_uids( KBNODE keyblock, strlist_t locusr, int *ret_modified, opt.cert_policy_url || opt.cert_notations) force_v4=1; - /* we have to use a copy of the sk, because make_keysig_packet + /* We have to use a copy of the pk, because make_keysig_packet * may remove the protection from sk and if we did other * changes to the secret key, we would save the unprotected - * version */ - if( sk ) - free_secret_key(sk); - sk = copy_secret_key( NULL, sk_rover->sk ); - keyid_from_sk( sk, sk_keyid ); + * version. FIXME: This can be removed because all protection + * is now done by gpg-agent. */ + if (pk) + free_public_key (pk); + pk = copy_public_key (NULL, sk_rover->pk); + keyid_from_pk (pk, sk_keyid); + /* set mark A for all selected user ids */ for( node=keyblock; node; node = node->next ) { if( select_all || (node->flag & NODFLG_SELUID) ) @@ -777,10 +779,10 @@ sign_uids( KBNODE keyblock, strlist_t locusr, int *ret_modified, if (!node->pkt->pkt.signature->flags.exportable && local) tty_printf(_( "\"%s\" was already locally signed by key %s\n"), - user,keystr_from_sk(sk)); + user,keystr_from_pk (pk)); else tty_printf(_("\"%s\" was already signed by key %s\n"), - user,keystr_from_sk(sk)); + user,keystr_from_pk (pk)); if(opt.expert && cpr_get_answer_is_yes("sign_uid.dupe_okay", @@ -793,8 +795,8 @@ sign_uids( KBNODE keyblock, strlist_t locusr, int *ret_modified, continue; } - sprintf (buf, "%08lX%08lX", - (ulong)sk->keyid[0], (ulong)sk->keyid[1] ); + snprintf (buf, sizeof buf, "%08lX%08lX", + (ulong)pk->keyid[0], (ulong)pk->keyid[1]); write_status_text (STATUS_ALREADY_SIGNED, buf); uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */ @@ -806,7 +808,7 @@ sign_uids( KBNODE keyblock, strlist_t locusr, int *ret_modified, /* check whether any uids are left for signing */ if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) { - tty_printf(_("Nothing to sign with key %s\n"),keystr_from_sk(sk)); + tty_printf (_("Nothing to sign with key %s\n"), keystr_from_pk (pk)); continue; } @@ -883,7 +885,7 @@ sign_uids( KBNODE keyblock, strlist_t locusr, int *ret_modified, currently v3 and we're about to sign it with a v4 sig? If so, danger! */ if(PGP2 && all_v3 && - (sk->version>3 || force_v4) && primary_pk->version<=3) + (pk->version > 3 || force_v4) && primary_pk->version <= 3) { tty_printf(_("You may not make an OpenPGP signature on a " "PGP 2.x key while in --pgp2 mode.\n")); @@ -953,8 +955,8 @@ sign_uids( KBNODE keyblock, strlist_t locusr, int *ret_modified, } p=get_user_id_native(sk_keyid); - tty_printf(_("Are you sure that you want to sign this key with your\n" - "key \"%s\" (%s)\n"),p,keystr_from_sk(sk)); + tty_printf (_("Are you sure that you want to sign this key with your\n" + "key \"%s\" (%s)\n"), p, keystr_from_pk (pk)); xfree(p); if(selfsig) @@ -1051,14 +1053,14 @@ sign_uids( KBNODE keyblock, strlist_t locusr, int *ret_modified, rc = make_keysig_packet( &sig, primary_pk, node->pkt->pkt.user_id, NULL, - sk, + pk, 0x13, 0, force_v4?4:0, 0, 0, keygen_add_std_prefs, primary_pk); else rc = make_keysig_packet( &sig, primary_pk, node->pkt->pkt.user_id, NULL, - sk, + pk, class, 0, force_v4?4:0, timestamp, duration, sign_mk_attrib, &attrib ); @@ -1086,8 +1088,8 @@ sign_uids( KBNODE keyblock, strlist_t locusr, int *ret_modified, leave: release_sk_list( sk_list ); - if( sk ) - free_secret_key(sk); + if (pk) + free_public_key (pk); return rc; } @@ -1653,7 +1655,7 @@ keyedit_menu( const char *username, strlist_t locusr, #ifdef HAVE_LIBREADLINE tty_enable_completion(keyedit_completion); #endif - answer = cpr_get_no_help("keyedit.prompt", _("Command> ")); + answer = cpr_get_no_help ("keyedit.prompt", "gpg> "); cpr_kill_prompt(); tty_disable_completion(); } @@ -2331,11 +2333,66 @@ keyedit_menu( const char *username, strlist_t locusr, void keyedit_passwd (const char *username) { - gpg_error_t err = gpg_error (GPG_ERR_BUG); /* Not yet implemented. */ + gpg_error_t err; + PKT_public_key *pk; + unsigned char fpr[MAX_FINGERPRINT_LEN]; + size_t fprlen; + KEYDB_HANDLE kdh = NULL; + kbnode_t keyblock = NULL; - log_info ("error changing the passphrase for `%s': %s\n", - username, gpg_strerror (err)); - write_status_error ("keyedit.passwd", err); + pk = xtrycalloc (1, sizeof *pk); + if (!pk) + { + err = gpg_error_from_syserror (); + goto leave; + } + err = getkey_byname (NULL, pk, username, 1, NULL); + if (err) + goto leave; + fingerprint_from_pk (pk, fpr, &fprlen); + while (fprlen < MAX_FINGERPRINT_LEN) + fpr[fprlen++] = 0; + + /* FIXME: Call an agent function instead. */ + + kdh = keydb_new (1); + if (!kdh) + { + err = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + err = keydb_search_fpr (kdh, fpr); + if (err == -1 || gpg_err_code (err) == GPG_ERR_EOF) + err = gpg_error (GPG_ERR_NO_SECKEY); + if (err) + goto leave; + + err = keydb_get_keyblock (kdh, &keyblock); + if (err) + goto leave; + + if (!change_passphrase (keyblock)) + { + err = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + err = keydb_update_keyblock (kdh, keyblock); + if (err) + log_error( _("update secret failed: %s\n"), gpg_strerror (err)); + + leave: + release_kbnode (keyblock); + if (pk) + free_public_key (pk); + keydb_release (kdh); + if (err) + { + log_info ("error changing the passphrase for `%s': %s\n", + username, gpg_strerror (err)); + write_status_error ("keyedit.passwd", err); + } } diff --git a/g10/keylist.c b/g10/keylist.c index 460e889b2..f5a977362 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -127,18 +127,18 @@ secret_key_list (strlist_t list) } void -print_seckey_info (PKT_secret_key * sk) +print_seckey_info (PKT_public_key *pk) { u32 keyid[2]; char *p; - keyid_from_sk (sk, keyid); + keyid_from_pk (pk, keyid); p = get_user_id_native (keyid); tty_printf ("\nsec %4u%c/%s %s %s\n", - nbits_from_sk (sk), - pubkey_letter (sk->pubkey_algo), - keystr (keyid), datestr_from_sk (sk), p); + nbits_from_pk (pk), + pubkey_letter (pk->pubkey_algo), + keystr (keyid), datestr_from_pk (pk), p); xfree (p); } @@ -423,7 +423,7 @@ list_all (int secret) memset (&stats, 0, sizeof (stats)); - hd = keydb_new (secret); + hd = keydb_new (0); if (!hd) rc = G10ERR_GENERAL; else @@ -444,23 +444,28 @@ list_all (int secret) log_error ("keydb_get_keyblock failed: %s\n", g10_errstr (rc)); goto leave; } - if (!opt.with_colons) - { - resname = keydb_get_resource_name (hd); - if (lastresname != resname) - { - int i; - - printf ("%s\n", resname); - for (i = strlen (resname); i; i--) - putchar ('-'); - putchar ('\n'); - lastresname = resname; - } - } - merge_keys_and_selfsig (keyblock); - list_keyblock (keyblock, secret, opt.fingerprint, - opt.check_sigs ? &stats : NULL); + if (secret && have_secret_key (keyblock)) + ; /* Secret key listing requested but this isn't one. */ + else + { + if (!opt.with_colons) + { + resname = keydb_get_resource_name (hd); + if (lastresname != resname) + { + int i; + + printf ("%s\n", resname); + for (i = strlen (resname); i; i--) + putchar ('-'); + putchar ('\n'); + lastresname = resname; + } + } + merge_keys_and_selfsig (keyblock); + list_keyblock (keyblock, secret, opt.fingerprint, + opt.check_sigs ? &stats : NULL); + } release_kbnode (keyblock); keyblock = NULL; } @@ -499,58 +504,31 @@ list_one (strlist_t names, int secret) * functions) or to have the search function return indicators for * found names. Yet another way is to use the keydb search * facilities directly. */ - if (secret) + rc = getkey_bynames (&ctx, NULL, names, secret, &keyblock); + if (rc) { - rc = get_seckey_bynames (&ctx, NULL, names, &keyblock); - if (rc) - { - log_error ("error reading key: %s\n", g10_errstr (rc)); - get_seckey_end (ctx); - return; - } - do - { - if ((opt.list_options & LIST_SHOW_KEYRING) && !opt.with_colons) - { - resname = keydb_get_resource_name (get_ctx_handle (ctx)); - printf ("%s: %s\n", keyring_str, resname); - for (i = strlen (resname) + strlen (keyring_str) + 2; i; i--) - putchar ('-'); - putchar ('\n'); - } - list_keyblock (keyblock, 1, opt.fingerprint, NULL); - release_kbnode (keyblock); - } - while (!get_seckey_next (ctx, NULL, &keyblock)); - get_seckey_end (ctx); - } - else - { - rc = get_pubkey_bynames (&ctx, NULL, names, &keyblock); - if (rc) - { - log_error ("error reading key: %s\n", g10_errstr (rc)); - get_pubkey_end (ctx); - return; - } - do - { - if ((opt.list_options & LIST_SHOW_KEYRING) && !opt.with_colons) - { - resname = keydb_get_resource_name (get_ctx_handle (ctx)); - printf ("%s: %s\n", keyring_str, resname); - for (i = strlen (resname) + strlen (keyring_str) + 2; i; i--) - putchar ('-'); - putchar ('\n'); - } - list_keyblock (keyblock, 0, opt.fingerprint, - opt.check_sigs ? &stats : NULL); - release_kbnode (keyblock); - } - while (!get_pubkey_next (ctx, NULL, &keyblock)); + log_error ("error reading key: %s\n", g10_errstr (rc)); get_pubkey_end (ctx); + return; } + do + { + if ((opt.list_options & LIST_SHOW_KEYRING) && !opt.with_colons) + { + resname = keydb_get_resource_name (get_ctx_handle (ctx)); + printf ("%s: %s\n", keyring_str, resname); + for (i = strlen (resname) + strlen (keyring_str) + 2; i; i--) + putchar ('-'); + putchar ('\n'); + } + list_keyblock (keyblock, secret, opt.fingerprint, + (!secret && opt.check_sigs)? &stats : NULL); + release_kbnode (keyblock); + } + while (!getkey_next (ctx, NULL, &keyblock)); + getkey_end (ctx); + if (opt.check_sigs && !opt.with_colons) print_signature_stats (&stats); } @@ -610,39 +588,37 @@ print_key_data (PKT_public_key * pk) } static void -print_capabilities (PKT_public_key * pk, PKT_secret_key * sk, KBNODE keyblock) +print_capabilities (PKT_public_key *pk, KBNODE keyblock) { - if (pk || (sk && sk->protect.s2k.mode != 1001)) + unsigned int use = pk->pubkey_usage; + int c_printed = 0; + + if (use & PUBKEY_USAGE_ENC) + putchar ('e'); + + if (use & PUBKEY_USAGE_SIG) { - unsigned int use = pk ? pk->pubkey_usage : sk->pubkey_usage; - int c_printed = 0; - - if (use & PUBKEY_USAGE_ENC) - putchar ('e'); - - if (use & PUBKEY_USAGE_SIG) - { - putchar ('s'); - if (pk ? pk->is_primary : sk->is_primary) - { - putchar ('c'); - /* The PUBKEY_USAGE_CERT flag was introduced later and - we used to always print 'c' for a primary key. To - avoid any regression here we better track whether we - printed 'c' already. */ - c_printed = 1; - } - } - - if ((use & PUBKEY_USAGE_CERT) && !c_printed) - putchar ('c'); - - if ((use & PUBKEY_USAGE_AUTH)) - putchar ('a'); + putchar ('s'); + if (pk->is_primary) + { + putchar ('c'); + /* The PUBKEY_USAGE_CERT flag was introduced later and we + used to always print 'c' for a primary key. To avoid any + regression here we better track whether we printed 'c' + already. */ + c_printed = 1; + } } + if ((use & PUBKEY_USAGE_CERT) && !c_printed) + putchar ('c'); + + if ((use & PUBKEY_USAGE_AUTH)) + putchar ('a'); + if (keyblock) - { /* figure out the usable capabilities */ + { + /* Figure out the usable capabilities. */ KBNODE k; int enc = 0, sign = 0, cert = 0, auth = 0, disabled = 0; @@ -672,27 +648,6 @@ print_capabilities (PKT_public_key * pk, PKT_secret_key * sk, KBNODE keyblock) auth = 1; } } - else if (k->pkt->pkttype == PKT_SECRET_KEY - || k->pkt->pkttype == PKT_SECRET_SUBKEY) - { - sk = k->pkt->pkt.secret_key; - if (sk->is_valid && !sk->is_revoked && !sk->has_expired - && sk->protect.s2k.mode != 1001) - { - if (sk->pubkey_usage & PUBKEY_USAGE_ENC) - enc = 1; - if (sk->pubkey_usage & PUBKEY_USAGE_SIG) - { - sign = 1; - if (sk->is_primary) - cert = 1; - } - if ((sk->pubkey_usage & PUBKEY_USAGE_CERT)) - cert = 1; - if ((sk->pubkey_usage & PUBKEY_USAGE_AUTH)) - auth = 1; - } - } } if (enc) putchar ('E'); @@ -705,10 +660,11 @@ print_capabilities (PKT_public_key * pk, PKT_secret_key * sk, KBNODE keyblock) if (disabled) putchar ('D'); } - + putchar (':'); } + /* FLAGS: 0x01 hashed 0x02 critical */ static void @@ -731,6 +687,7 @@ print_one_subpacket (sigsubpkttype_t type, size_t len, int flags, printf ("\n"); } + void print_subpackets_colon (PKT_signature * sig) { @@ -756,9 +713,9 @@ print_subpackets_colon (PKT_signature * sig) } } + void -dump_attribs (const PKT_user_id * uid, PKT_public_key * pk, - PKT_secret_key * sk) +dump_attribs (const PKT_user_id *uid, PKT_public_key *pk) { int i; @@ -773,12 +730,9 @@ dump_attribs (const PKT_user_id * uid, PKT_public_key * pk, char buf[(MAX_FINGERPRINT_LEN * 2) + 90]; size_t j, n; - if (pk) - fingerprint_from_pk (pk, array, &n); - else if (sk) - fingerprint_from_sk (sk, array, &n); - else - BUG (); + if (!pk) + BUG (); + fingerprint_from_pk (pk, array, &n); p = array; for (j = 0; j < n; j++, p++) @@ -799,6 +753,7 @@ dump_attribs (const PKT_user_id * uid, PKT_public_key * pk, } } + static void list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) { @@ -806,12 +761,12 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) KBNODE kbctx; KBNODE node; PKT_public_key *pk; - PKT_secret_key *sk; struct sig_stats *stats = opaque; int skip_sigs = 0; + int s2k_char; - /* get the keyid from the keyblock */ - node = find_kbnode (keyblock, secret ? PKT_SECRET_KEY : PKT_PUBLIC_KEY); + /* Get the keyid from the keyblock. */ + node = find_kbnode (keyblock, PKT_PUBLIC_KEY); if (!node) { log_error ("Oops; key lost!\n"); @@ -819,81 +774,57 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) return; } - if (secret) + pk = node->pkt->pkt.public_key; + + /* Fixme: Get s2k mode from the agent. */ + s2k_char = (/*(sk->protect.s2k.mode == 1001)? '#' : + (sk->protect.s2k.mode == 1002)? '>' : */' '); + + check_trustdb_stale (); + + printf ("%s%c %4u%c/%s %s", + secret? "sec":"pub", + s2k_char, + nbits_from_pk (pk), pubkey_letter (pk->pubkey_algo), + keystr_from_pk (pk), datestr_from_pk (pk)); + + if (pk->is_revoked) { - pk = NULL; - sk = node->pkt->pkt.secret_key; - - printf ("sec%c %4u%c/%s %s", (sk->protect.s2k.mode == 1001) ? '#' : - (sk->protect.s2k.mode == 1002) ? '>' : ' ', - nbits_from_sk (sk), pubkey_letter (sk->pubkey_algo), - keystr_from_sk (sk), datestr_from_sk (sk)); - - if (sk->has_expired) - { - printf (" ["); - printf (_("expired: %s"), expirestr_from_sk (sk)); - printf ("]"); - } - else if (sk->expiredate) - { - printf (" ["); - printf (_("expires: %s"), expirestr_from_sk (sk)); - printf ("]"); - } - - printf ("\n"); + printf (" ["); + printf (_("revoked: %s"), revokestr_from_pk (pk)); + printf ("]"); } - else + else if (pk->has_expired) { - pk = node->pkt->pkt.public_key; - sk = NULL; - - check_trustdb_stale (); - - printf ("pub %4u%c/%s %s", - nbits_from_pk (pk), pubkey_letter (pk->pubkey_algo), - keystr_from_pk (pk), datestr_from_pk (pk)); - - /* We didn't include this before in the key listing, but there - is room in the new format, so why not? */ - - if (pk->is_revoked) - { - printf (" ["); - printf (_("revoked: %s"), revokestr_from_pk (pk)); - printf ("]"); - } - else if (pk->has_expired) - { - printf (" ["); - printf (_("expired: %s"), expirestr_from_pk (pk)); - printf ("]"); - } - else if (pk->expiredate) - { - printf (" ["); - printf (_("expires: %s"), expirestr_from_pk (pk)); - printf ("]"); - } + printf (" ["); + printf (_("expired: %s"), expirestr_from_pk (pk)); + printf ("]"); + } + else if (pk->expiredate) + { + printf (" ["); + printf (_("expires: %s"), expirestr_from_pk (pk)); + printf ("]"); + } #if 0 - /* I need to think about this some more. It's easy enough to - include, but it looks sort of confusing in the - listing... */ - if (opt.list_options & LIST_SHOW_VALIDITY) - { - int validity = get_validity (pk, NULL); - printf (" [%s]", trust_value_to_string (validity)); - } + /* I need to think about this some more. It's easy enough to + include, but it looks sort of confusing in the listing... */ + if (opt.list_options & LIST_SHOW_VALIDITY) + { + int validity = get_validity (pk, NULL); + printf (" [%s]", trust_value_to_string (validity)); + } #endif - printf ("\n"); - } + printf ("\n"); if (fpr) - print_fingerprint (pk, sk, 0); - print_card_serialno (sk); + print_fingerprint (pk, NULL, 0); + + /* FIXME: Change this function to take a PK and ask the agent: */ + /* if (secret) print_card_serialno (sk); */ + if (opt.with_key_data) print_key_data (pk); @@ -913,7 +844,7 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) skip_sigs = 0; if (attrib_fp && uid->attrib_data != NULL) - dump_attribs (uid, pk, sk); + dump_attribs (uid, pk); if ((uid->is_revoked || uid->is_expired) || ((opt.list_options & LIST_SHOW_UID_VALIDITY) && pk)) @@ -938,7 +869,7 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) putchar ('\n'); if ((opt.list_options & LIST_SHOW_PHOTOS) && uid->attribs != NULL) - show_photos (uid->attribs, uid->numattribs, pk, sk, uid); + show_photos (uid->attribs, uid->numattribs, pk, NULL, uid); } else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) { @@ -953,7 +884,13 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) else skip_sigs = 0; - printf ("sub %4u%c/%s %s", + /* Fixme: Get s2k mode from the agent. */ + s2k_char = (/*(sk->protect.s2k.mode == 1001)? '#' : + (sk->protect.s2k.mode == 1002)? '>' : */' '); + + printf ("%s%c %4u%c/%s %s", + secret? "ssb":"sub", + s2k_char, nbits_from_pk (pk2), pubkey_letter (pk2->pubkey_algo), keystr_from_pk (pk2), datestr_from_pk (pk2)); if (pk2->is_revoked) @@ -976,32 +913,15 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) } putchar ('\n'); if (fpr > 1) - print_fingerprint (pk2, NULL, 0); + { + print_fingerprint (pk2, NULL, 0); + /* FIXME: (see above) */ + /* if (secret) */ + /* print_card_serialno (sk2); */ + } if (opt.with_key_data) print_key_data (pk2); } - else if (node->pkt->pkttype == PKT_SECRET_SUBKEY) - { - PKT_secret_key *sk2 = node->pkt->pkt.secret_key; - - printf ("ssb%c %4u%c/%s %s", - (sk2->protect.s2k.mode == 1001) ? '#' : - (sk2->protect.s2k.mode == 1002) ? '>' : ' ', - nbits_from_sk (sk2), pubkey_letter (sk2->pubkey_algo), - keystr_from_sk (sk2), datestr_from_sk (sk2)); - if (sk2->expiredate) - { - printf (" ["); - printf (_("expires: %s"), expirestr_from_sk (sk2)); - printf ("]"); - } - putchar ('\n'); - if (fpr > 1) - { - print_fingerprint (NULL, sk2, 0); - print_card_serialno (sk2); - } - } else if (opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE && !skip_sigs) { @@ -1142,14 +1062,13 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr) KBNODE kbctx; KBNODE node; PKT_public_key *pk; - PKT_secret_key *sk; u32 keyid[2]; int trustletter = 0; int ulti_hack = 0; int i; - /* get the keyid from the keyblock */ - node = find_kbnode (keyblock, secret ? PKT_SECRET_KEY : PKT_PUBLIC_KEY); + /* Get the keyid from the keyblock. */ + node = find_kbnode (keyblock, PKT_PUBLIC_KEY); if (!node) { log_error ("Oops; key lost!\n"); @@ -1157,77 +1076,63 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr) return; } - if (secret) - { - pk = NULL; - sk = node->pkt->pkt.secret_key; - keyid_from_sk (sk, keyid); - printf ("sec::%u:%d:%08lX%08lX:%s:%s:::", - nbits_from_sk (sk), - sk->pubkey_algo, - (ulong) keyid[0], (ulong) keyid[1], - colon_datestr_from_sk (sk), colon_strtime (sk->expiredate) - /* fixme: add LID here */ ); - } + pk = node->pkt->pkt.public_key; + + keyid_from_pk (pk, keyid); + fputs (secret? "sec:":"pub:", stdout); + if (!pk->is_valid) + putchar ('i'); + else if (pk->is_revoked) + putchar ('r'); + else if (pk->has_expired) + putchar ('e'); + else if (opt.fast_list_mode || opt.no_expensive_trust_checks) + ; else { - pk = node->pkt->pkt.public_key; - sk = NULL; - keyid_from_pk (pk, keyid); - fputs ("pub:", stdout); - if (!pk->is_valid) - putchar ('i'); - else if (pk->is_revoked) - putchar ('r'); - else if (pk->has_expired) - putchar ('e'); - else if (opt.fast_list_mode || opt.no_expensive_trust_checks) - ; - else - { - trustletter = get_validity_info (pk, NULL); - if (trustletter == 'u') - ulti_hack = 1; - putchar (trustletter); - } - printf (":%u:%d:%08lX%08lX:%s:%s::", - nbits_from_pk (pk), - pk->pubkey_algo, - (ulong) keyid[0], (ulong) keyid[1], - colon_datestr_from_pk (pk), colon_strtime (pk->expiredate)); - if (!opt.fast_list_mode && !opt.no_expensive_trust_checks) - putchar (get_ownertrust_info (pk)); - putchar (':'); + trustletter = get_validity_info (pk, NULL); + if (trustletter == 'u') + ulti_hack = 1; + putchar (trustletter); } + printf (":%u:%d:%08lX%08lX:%s:%s::", + nbits_from_pk (pk), + pk->pubkey_algo, + (ulong) keyid[0], (ulong) keyid[1], + colon_datestr_from_pk (pk), colon_strtime (pk->expiredate)); + + if (!opt.fast_list_mode && !opt.no_expensive_trust_checks) + putchar (get_ownertrust_info (pk)); + putchar (':'); + putchar (':'); putchar (':'); - print_capabilities (pk, sk, keyblock); + print_capabilities (pk, keyblock); if (secret) { putchar (':'); /* End of field 13. */ putchar (':'); /* End of field 14. */ - if (sk->protect.s2k.mode == 1001) + if (/*FIXME sk->protect.s2k.mode*/1 == 1001) putchar ('#'); /* Key is just a stub. */ - else if (sk->protect.s2k.mode == 1002) + else if (/*FIXME sk->protect.s2k.mode*/1 == 1002) { /* Key is stored on an external token (card) or handled by the gpg-agent. Print the serial number of that token here. */ - for (i = 0; i < sk->protect.ivlen; i++) - printf ("%02X", sk->protect.iv[i]); + /* FIXME: for (i = 0; i < sk->protect.ivlen; i++) */ + /* printf ("%02X", sk->protect.iv[i]); */ } putchar (':'); /* End of field 15. */ } putchar ('\n'); - if (pk) - print_revokers (pk); + + print_revokers (pk); if (fpr) - print_fingerprint (pk, sk, 0); + print_fingerprint (pk, NULL, 0); if (opt.with_key_data) print_key_data (pk); - - + for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));) { if (node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode) @@ -1236,16 +1141,12 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr) PKT_user_id *uid = node->pkt->pkt.user_id; if (attrib_fp && node->pkt->pkt.user_id->attrib_data != NULL) - dump_attribs (node->pkt->pkt.user_id, pk, sk); + dump_attribs (node->pkt->pkt.user_id, pk); /* * Fixme: We need a is_valid flag here too */ str = uid->attrib_data ? "uat" : "uid"; - /* If we're listing a secret key, leave out the validity - values for now. This is handled better in 1.9. */ - if (sk) - printf ("%s:::::", str); - else if (uid->is_revoked) + if (uid->is_revoked) printf ("%s:r::::", str); else if (uid->is_expired) printf ("%s:e::::", str); @@ -1285,7 +1186,7 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr) PKT_public_key *pk2 = node->pkt->pkt.public_key; keyid_from_pk (pk2, keyid2); - fputs ("sub:", stdout); + fputs (secret? "ssb:":"sub:", stdout); if (!pk2->is_valid) putchar ('i'); else if (pk2->is_revoked) @@ -1307,44 +1208,29 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr) colon_datestr_from_pk (pk2), colon_strtime (pk2->expiredate) /* fixme: add LID and ownertrust here */ ); - print_capabilities (pk2, NULL, NULL); + print_capabilities (pk2, NULL); + if (secret) + { + putchar (':'); /* End of field 13. */ + putchar (':'); /* End of field 14. */ + if (/*FIXME:sk2->protect.s2k.mode*/1 == 1001) + putchar ('#'); /* Key is just a stub. */ + else if (/*FIXME: sk2->protect.s2k.mode*/1 == 1002) + { + /* Key is stored on an external token (card) or + handled by the gpg-agent. Print the serial + number of that token here. */ + /* FIXME: for (i = 0; i < sk2->protect.ivlen; i++) + printf ("%02X", sk2->protect.iv[i]); */ + } + putchar (':'); /* End of field 15. */ + } putchar ('\n'); if (fpr > 1) print_fingerprint (pk2, NULL, 0); if (opt.with_key_data) print_key_data (pk2); } - else if (node->pkt->pkttype == PKT_SECRET_SUBKEY) - { - u32 keyid2[2]; - PKT_secret_key *sk2 = node->pkt->pkt.secret_key; - - keyid_from_sk (sk2, keyid2); - printf ("ssb::%u:%d:%08lX%08lX:%s:%s:::::", - nbits_from_sk (sk2), - sk2->pubkey_algo, - (ulong) keyid2[0], (ulong) keyid2[1], - colon_datestr_from_sk (sk2), colon_strtime (sk2->expiredate) - /* fixme: add LID */ ); - print_capabilities (NULL, sk2, NULL); - putchar (':'); /* End of field 13. */ - putchar (':'); /* End of field 14. */ - if (sk2->protect.s2k.mode == 1001) - putchar ('#'); /* Key is just a stub. */ - else if (sk2->protect.s2k.mode == 1002) - { - /* Key is stored on an external token (card) or handled by - the gpg-agent. Print the serial number of that token - here. */ - for (i = 0; i < sk2->protect.ivlen; i++) - printf ("%02X", sk2->protect.iv[i]); - } - putchar (':'); /* End of field 15. */ - putchar ('\n'); - - if (fpr > 1) - print_fingerprint (NULL, sk2, 0); - } else if (opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE) { PKT_signature *sig = node->pkt->pkt.signature; diff --git a/g10/main.h b/g10/main.h index 90f005851..1d31f476d 100644 --- a/g10/main.h +++ b/g10/main.h @@ -103,7 +103,7 @@ void idea_cipher_warn( int show ); struct expando_args { PKT_public_key *pk; - PKT_secret_key *sk; + PKT_public_key *pksk; byte imagetype; int validity_info; const char *validity_string; @@ -195,7 +195,7 @@ int encrypt_filter (void *opaque, int control, /*-- sign.c --*/ -int complete_sig( PKT_signature *sig, PKT_secret_key *sk, gcry_md_hd_t md ); +int complete_sig (PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md); int sign_file( strlist_t filenames, int detached, strlist_t locusr, int do_encrypt, strlist_t remusr, const char *outfile ); int clearsign_file( const char *fname, strlist_t locusr, const char *outfile ); @@ -306,10 +306,9 @@ void print_revokers(PKT_public_key *pk); void show_policy_url(PKT_signature *sig,int indent,int mode); void show_keyserver_url(PKT_signature *sig,int indent,int mode); void show_notation(PKT_signature *sig,int indent,int mode,int which); -void dump_attribs(const PKT_user_id *uid, - PKT_public_key *pk,PKT_secret_key *sk); +void dump_attribs (const PKT_user_id *uid, PKT_public_key *pk); void set_attrib_fd(int fd); -void print_seckey_info (PKT_secret_key *sk); +void print_seckey_info (PKT_public_key *pk); void print_pubkey_info (FILE *fp, PKT_public_key *pk); void print_card_key_info (FILE *fp, KBNODE keyblock); diff --git a/g10/mainproc.c b/g10/mainproc.c index 8178db2ae..8707cd8c8 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1837,7 +1837,7 @@ check_sig_and_print( CTX c, KBNODE node ) if(un->pkt->pkt.user_id->attrib_data) { - dump_attribs(un->pkt->pkt.user_id,pk,NULL); + dump_attribs (un->pkt->pkt.user_id, pk); if(opt.verify_options&VERIFY_SHOW_PHOTOS) show_photos(un->pkt->pkt.user_id->attribs, diff --git a/g10/misc.c b/g10/misc.c index 8cc63ba34..f34e1e36d 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -510,15 +510,16 @@ idea_cipher_warn(int show) static unsigned long -get_signature_count (PKT_secret_key *sk) +get_signature_count (PKT_public_key *pk) { #ifdef ENABLE_CARD_SUPPORT - if(sk && sk->is_protected && sk->protect.s2k.mode==1002) - { - struct agent_card_info_s info; - if(agent_scd_getattr("SIG-COUNTER",&info)==0) - return info.sig_counter; - } + /* FIXME: Need to call the agent. */ + /* if(sk && sk->is_protected && sk->protect.s2k.mode==1002) */ + /* { */ + /* struct agent_card_info_s info; */ + /* if(agent_scd_getattr("SIG-COUNTER",&info)==0) */ + /* return info.sig_counter; */ + /* } */ #endif /* How to do this without a card? */ @@ -539,13 +540,13 @@ pct_expando(const char *string,struct expando_args *args) if(args->pk) keyid_from_pk(args->pk,pk_keyid); - if(args->sk) - keyid_from_sk(args->sk,sk_keyid); + if(args->pksk) + keyid_from_pk (args->pksk, sk_keyid); /* This is used so that %k works in photoid command strings in --list-secret-keys (which of course has a sk, but no pk). */ - if(!args->pk && args->sk) - keyid_from_sk(args->sk,pk_keyid); + if(!args->pk && args->pksk) + keyid_from_pk (args->pksk, pk_keyid); while(*ch!='\0') { @@ -606,7 +607,7 @@ pct_expando(const char *string,struct expando_args *args) case 'c': /* signature count from card, if any. */ if(idx+10sk)); + sprintf (&ret[idx],"%lu", get_signature_count (args->pksk)); idx+=strlen(&ret[idx]); done=1; } @@ -620,28 +621,31 @@ pct_expando(const char *string,struct expando_args *args) size_t len; int i; - if((*(ch+1))=='p' && args->sk) + if((*(ch+1))=='p' && args->pksk) { - if(args->sk->is_primary) - fingerprint_from_sk(args->sk,array,&len); - else if(args->sk->main_keyid[0] || args->sk->main_keyid[1]) + if(args->pksk->is_primary) + fingerprint_from_pk (args->pksk, array, &len); + else if (args->pksk->main_keyid[0] + || args->pksk->main_keyid[1]) { + /* FIXME: Document teh code and check whether + it is still needed. */ PKT_public_key *pk= xmalloc_clear(sizeof(PKT_public_key)); - if(get_pubkey_fast(pk,args->sk->main_keyid)==0) - fingerprint_from_pk(pk,array,&len); + if (!get_pubkey_fast (pk,args->pksk->main_keyid)) + fingerprint_from_pk (pk, array, &len); else - memset(array,0,(len=MAX_FINGERPRINT_LEN)); - free_public_key(pk); + memset (array, 0, (len=MAX_FINGERPRINT_LEN)); + free_public_key (pk); } else memset(array,0,(len=MAX_FINGERPRINT_LEN)); } else if((*(ch+1))=='f' && args->pk) - fingerprint_from_pk(args->pk,array,&len); - else if((*(ch+1))=='g' && args->sk) - fingerprint_from_sk(args->sk,array,&len); + fingerprint_from_pk (args->pk, array, &len); + else if((*(ch+1))=='g' && args->pksk) + fingerprint_from_pk (args->pksk, array, &len); else memset(array,0,(len=MAX_FINGERPRINT_LEN)); diff --git a/g10/packet.h b/g10/packet.h index 2ceaba4f3..a97fe07a3 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -501,7 +501,7 @@ int ask_for_detached_datafile( gcry_md_hd_t md, gcry_md_hd_t md2, /*-- sign.c --*/ int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, - PKT_secret_key *sk, int sigclass, int digest_algo, + PKT_public_key *pksk, int sigclass, int digest_algo, int sigversion, u32 timestamp, u32 duration, int (*mksubpkt)(PKT_signature *, void *), void *opaque ); @@ -510,7 +510,7 @@ int update_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, - PKT_secret_key *sk, + PKT_public_key *pksk, int (*mksubpkt)(PKT_signature *, void *), void *opaque ); diff --git a/g10/photoid.c b/g10/photoid.c index 8aa4ad491..1ac1218d7 100644 --- a/g10/photoid.c +++ b/g10/photoid.c @@ -297,7 +297,7 @@ show_photos(const struct user_attribute *attrs, memset(&args,0,sizeof(args)); args.pk=pk; - args.sk=sk; + args.pksk=sk; args.validity_info=get_validity_info(pk,uid); args.validity_string=get_validity_string(pk,uid); diff --git a/g10/revoke.c b/g10/revoke.c index 38b955625..5e22a709a 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -200,7 +200,7 @@ gen_desig_revoke( const char *uname, strlist_t locusr ) int rc = 0; armor_filter_context_t *afx; PKT_public_key *pk = NULL; - PKT_secret_key *sk = NULL; + PKT_public_key *pk2 = NULL; PKT_signature *sig = NULL; IOBUF out = NULL; struct revocation_reason_info *reason = NULL; @@ -262,8 +262,8 @@ gen_desig_revoke( const char *uname, strlist_t locusr ) { SK_LIST list; - if(sk) - free_secret_key(sk); + if (pk2) + free_public_key (pk2); if(sk_list) { @@ -272,7 +272,7 @@ gen_desig_revoke( const char *uname, strlist_t locusr ) byte fpr[MAX_FINGERPRINT_LEN]; size_t fprlen; - fingerprint_from_sk(list->sk,fpr,&fprlen); + fingerprint_from_pk (list->pk, fpr, &fprlen); /* Don't get involved with keys that don't have 160 bit fingerprints */ @@ -283,18 +283,19 @@ gen_desig_revoke( const char *uname, strlist_t locusr ) break; } - if(list) - sk=copy_secret_key(NULL,list->sk); + if (list) + pk2 = copy_public_key (NULL, list->pk); else continue; } else { - sk=xmalloc_secure_clear(sizeof(*sk)); - rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN); + pk2 = xmalloc_clear (sizeof *pk2); + rc = get_pubkey_byfprint (pk2, + pk->revkey[i].fpr, MAX_FINGERPRINT_LEN); } - /* We have the revocation key */ + /* We have the revocation key. */ if(!rc) { PKT_signature *revkey = NULL; @@ -305,7 +306,7 @@ gen_desig_revoke( const char *uname, strlist_t locusr ) tty_printf ("\n"); tty_printf (_("To be revoked by:\n")); - print_seckey_info (sk); + print_seckey_info (pk2); if(pk->revkey[i].class&0x40) tty_printf(_("(This is a sensitive revocation key)\n")); @@ -320,8 +321,8 @@ gen_desig_revoke( const char *uname, strlist_t locusr ) if( !reason ) continue; - rc = check_secret_key( sk, 0 ); - if( rc ) + rc = -1;/*FIXME: check_secret_key (pk2, 0 );*/ + if (rc) continue; if( !opt.armor ) @@ -336,7 +337,7 @@ gen_desig_revoke( const char *uname, strlist_t locusr ) push_armor_filter (afx, out); /* create it */ - rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, + rc = make_keysig_packet( &sig, pk, NULL, NULL, pk2, 0x20, 0, 0, 0, 0, revocation_reason_build_cb, reason ); if( rc ) { @@ -414,8 +415,8 @@ gen_desig_revoke( const char *uname, strlist_t locusr ) leave: if( pk ) free_public_key( pk ); - if( sk ) - free_secret_key( sk ); + if (pk2) + free_public_key (pk2); if( sig ) free_seckey_enc( sig ); diff --git a/g10/server.c b/g10/server.c index 37acceebf..1be1ab3c2 100644 --- a/g10/server.c +++ b/g10/server.c @@ -611,6 +611,7 @@ cmd_passwd (assuan_context_t ctx, char *line) /* ctrl_t ctrl = assuan_get_pointer (ctx); */ gpg_error_t err; + (void)ctx; line = skip_options (line); err = gpg_error (GPG_ERR_NOT_SUPPORTED); diff --git a/g10/sign.c b/g10/sign.c index 92617a981..9c732799f 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -1,6 +1,6 @@ /* sign.c - sign data * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - * 2007 Free Software Foundation, Inc. + * 2007, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -57,8 +57,8 @@ static int recipient_digest_algo=0; * a valid NAME=VALUE format. */ static void -mk_notation_policy_etc( PKT_signature *sig, - PKT_public_key *pk, PKT_secret_key *sk ) +mk_notation_policy_etc (PKT_signature *sig, + PKT_public_key *pk, PKT_public_key *pksk) { const char *string; char *s=NULL; @@ -70,7 +70,7 @@ mk_notation_policy_etc( PKT_signature *sig, memset(&args,0,sizeof(args)); args.pk=pk; - args.sk=sk; + args.pksk=pksk; /* notation data */ if(IS_SIG(sig) && opt.sig_notations) @@ -229,15 +229,15 @@ hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig) static int -do_sign( PKT_secret_key *sk, PKT_signature *sig, - gcry_md_hd_t md, int digest_algo ) +do_sign (PKT_public_key *pksk, PKT_signature *sig, + gcry_md_hd_t md, int digest_algo) { gcry_mpi_t frame; byte *dp; int rc; - if( sk->timestamp > sig->timestamp ) { - ulong d = sk->timestamp - sig->timestamp; + if (pksk->timestamp > sig->timestamp ) { + ulong d = pksk->timestamp - sig->timestamp; log_info( d==1 ? _("key has been created %lu second " "in future (time warp or clock problem)\n") : _("key has been created %lu seconds " @@ -247,7 +247,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, } - print_pubkey_algo_note(sk->pubkey_algo); + print_pubkey_algo_note (pksk->pubkey_algo); if( !digest_algo ) digest_algo = gcry_md_get_algo (md); @@ -257,37 +257,39 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, sig->digest_algo = digest_algo; sig->digest_start[0] = dp[0]; sig->digest_start[1] = dp[1]; - if (sk->is_protected && sk->protect.s2k.mode == 1002) - { -#ifdef ENABLE_CARD_SUPPORT - unsigned char *rbuf; - size_t rbuflen; - char *snbuf; + + /* FIXME: Use agent. */ +/* if (pksk->is_protected && pksk->protect.s2k.mode == 1002) */ +/* { */ +/* #ifdef ENABLE_CARD_SUPPORT */ +/* unsigned char *rbuf; */ +/* size_t rbuflen; */ +/* char *snbuf; */ - snbuf = serialno_and_fpr_from_sk (sk->protect.iv, - sk->protect.ivlen, sk); - rc = agent_scd_pksign (snbuf, digest_algo, - gcry_md_read (md, digest_algo), - gcry_md_get_algo_dlen (digest_algo), - &rbuf, &rbuflen); - xfree (snbuf); - if (!rc) - { - if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, - rbuf, rbuflen, NULL)) - BUG (); - xfree (rbuf); - } -#else - return gpg_error (GPG_ERR_NOT_SUPPORTED); -#endif /* ENABLE_CARD_SUPPORT */ - } - else +/* snbuf = serialno_and_fpr_from_sk (sk->protect.iv, */ +/* sk->protect.ivlen, sk); */ +/* rc = agent_scd_pksign (snbuf, digest_algo, */ +/* gcry_md_read (md, digest_algo), */ +/* gcry_md_get_algo_dlen (digest_algo), */ +/* &rbuf, &rbuflen); */ +/* xfree (snbuf); */ +/* if (!rc) */ +/* { */ +/* if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, */ +/* rbuf, rbuflen, NULL)) */ +/* BUG (); */ +/* xfree (rbuf); */ +/* } */ +/* #else */ +/* return gpg_error (GPG_ERR_NOT_SUPPORTED); */ +/* #endif /\* ENABLE_CARD_SUPPORT *\/ */ +/* } */ +/* else */ { - frame = encode_md_value( NULL, sk, md, digest_algo ); + frame = encode_md_value (NULL, pksk, md, digest_algo ); if (!frame) return G10ERR_GENERAL; - rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey ); + rc = pk_sign (pksk->pubkey_algo, sig->data, frame, pksk->pkey ); gcry_mpi_release (frame); } @@ -318,7 +320,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, if( opt.verbose ) { char *ustr = get_user_id_string_native (sig->keyid); log_info(_("%s/%s signature from: \"%s\"\n"), - gcry_pk_algo_name (sk->pubkey_algo), + gcry_pk_algo_name (pksk->pubkey_algo), gcry_md_algo_name (sig->digest_algo), ustr ); xfree(ustr); @@ -329,13 +331,13 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, int -complete_sig( PKT_signature *sig, PKT_secret_key *sk, gcry_md_hd_t md ) +complete_sig( PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md ) { - int rc=0; + int rc; - if( !(rc=check_secret_key( sk, 0 )) ) - rc = do_sign( sk, sig, md, 0 ); - return rc; + if (!(rc = check_secret_key (pksk, 0))) + rc = do_sign (pksk, sig, md, 0); + return rc; } @@ -378,15 +380,19 @@ match_dsa_hash (unsigned int qbytes) list? */ static int -hash_for(PKT_secret_key *sk) +hash_for (PKT_public_key *pk) { - if( opt.def_digest_algo ) - return opt.def_digest_algo; - else if( recipient_digest_algo ) - return recipient_digest_algo; - else if(sk->pubkey_algo==PUBKEY_ALGO_DSA) + if (opt.def_digest_algo) { - unsigned int qbytes = gcry_mpi_get_nbits (sk->skey[1]) / 8; + return opt.def_digest_algo; + } + else if (recipient_digest_algo) + { + return recipient_digest_algo; + } + else if (pk->pubkey_algo == PUBKEY_ALGO_DSA) + { + unsigned int qbytes = gcry_mpi_get_nbits (pk->pkey[1]) / 8; /* It's a DSA key, so find a hash that is the same size as q or larger. If q is 160, assume it is an old DSA key and use a @@ -415,9 +421,10 @@ hash_for(PKT_secret_key *sk) return match_dsa_hash(qbytes); } - else if (sk->is_protected && sk->protect.s2k.mode==1002) + else if (/*FIXME: call agent + pk->is_protected && sk->protect.s2k.mode==1002*/ 0) { - /* The sk lives on a smartcard, and current smartcards only + /* The secret key lives on a smartcard, and current smartcards only handle SHA-1 and RIPEMD/160. This is correct now, but may need revision as the cards add algorithms. */ @@ -433,12 +440,12 @@ hash_for(PKT_secret_key *sk) return DIGEST_ALGO_SHA1; } - else if (PGP2 && sk->pubkey_algo == PUBKEY_ALGO_RSA && sk->version < 4 ) + else if (PGP2 && pk->pubkey_algo == PUBKEY_ALGO_RSA && pk->version < 4 ) { /* Old-style PGP only understands MD5 */ return DIGEST_ALGO_MD5; } - else if ( opt.personal_digest_prefs ) + else if (opt.personal_digest_prefs) { /* It's not DSA, so we can use whatever the first hash algorithm is in the pref list */ @@ -449,42 +456,40 @@ hash_for(PKT_secret_key *sk) } +/* Return true iff all keys in SK_LIST are old style (v3 RSA). */ static int -only_old_style( SK_LIST sk_list ) +only_old_style (SK_LIST sk_list) { - SK_LIST sk_rover = NULL; - int old_style = 0; + SK_LIST sk_rover = NULL; + int old_style = 0; + + for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) + { + PKT_public_key *pk = sk_rover->pk; - /* if there are only old style capable key we use the old sytle */ - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk = sk_rover->sk; - if( sk->pubkey_algo == PUBKEY_ALGO_RSA && sk->version < 4 ) - old_style = 1; - else - return 0; + if (pk->pubkey_algo == PUBKEY_ALGO_RSA && pk->version < 4) + old_style = 1; + else + return 0; } - return old_style; + return old_style; } - static void -print_status_sig_created ( PKT_secret_key *sk, PKT_signature *sig, int what ) +print_status_sig_created (PKT_public_key *pk, PKT_signature *sig, int what) { - byte array[MAX_FINGERPRINT_LEN], *p; - char buf[100+MAX_FINGERPRINT_LEN*2]; - size_t i, n; - - sprintf(buf, "%c %d %d %02x %lu ", - what, sig->pubkey_algo, sig->digest_algo, sig->sig_class, - (ulong)sig->timestamp ); - - fingerprint_from_sk( sk, array, &n ); - p = buf + strlen(buf); - for(i=0; i < n ; i++ ) - sprintf(p+2*i, "%02X", array[i] ); - - write_status_text( STATUS_SIG_CREATED, buf ); + byte array[MAX_FINGERPRINT_LEN]; + char buf[100+MAX_FINGERPRINT_LEN*2]; + size_t n; + + snprintf (buf, sizeof buf - 2*MAX_FINGERPRINT_LEN, "%c %d %d %02x %lu ", + what, sig->pubkey_algo, sig->digest_algo, sig->sig_class, + (ulong)sig->timestamp ); + fingerprint_from_pk (pk, array, &n); + bin2hex (array, n, buf + strlen (buf)); + + write_status_text( STATUS_SIG_CREATED, buf ); } @@ -504,7 +509,7 @@ write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass ) skcount++; for (; skcount; skcount--) { - PKT_secret_key *sk; + PKT_public_key *pk; PKT_onepass_sig *ops; PACKET pkt; int i, rc; @@ -514,12 +519,12 @@ write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass ) break; } - sk = sk_rover->sk; + pk = sk_rover->pk; ops = xmalloc_clear (sizeof *ops); ops->sig_class = sigclass; - ops->digest_algo = hash_for (sk); - ops->pubkey_algo = sk->pubkey_algo; - keyid_from_sk (sk, ops->keyid); + ops->digest_algo = hash_for (pk); + ops->pubkey_algo = pk->pubkey_algo; + keyid_from_pk (pk, ops->keyid); ops->last = (skcount == 1); init_packet(&pkt); @@ -622,73 +627,76 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash, int sigclass, u32 timestamp, u32 duration, int status_letter) { - SK_LIST sk_rover; + SK_LIST sk_rover; + + /* Loop over the certificates with secret keys. */ + for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) + { + PKT_public_key *pk; + PKT_signature *sig; + gcry_md_hd_t md; + int rc; - /* loop over the secret certificates */ - for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { - PKT_secret_key *sk; - PKT_signature *sig; - gcry_md_hd_t md; - int rc; + pk = sk_rover->pk; - sk = sk_rover->sk; + /* Build the signature packet. */ + sig = xmalloc_clear (sizeof *sig); + if (opt.force_v3_sigs || RFC1991) + sig->version = 3; + else if (duration || opt.sig_policy_url + || opt.sig_notations || opt.sig_keyserver_url) + sig->version = 4; + else + sig->version = pk->version; - /* build the signature packet */ - sig = xmalloc_clear (sizeof *sig); - if(opt.force_v3_sigs || RFC1991) - sig->version=3; - else if(duration || opt.sig_policy_url - || opt.sig_notations || opt.sig_keyserver_url) - sig->version=4; - else - sig->version=sk->version; - keyid_from_sk (sk, sig->keyid); - sig->digest_algo = hash_for(sk); - sig->pubkey_algo = sk->pubkey_algo; - if(timestamp) - sig->timestamp = timestamp; - else - sig->timestamp = make_timestamp(); - if(duration) - sig->expiredate = sig->timestamp+duration; - sig->sig_class = sigclass; + keyid_from_pk (pk, sig->keyid); + sig->digest_algo = hash_for (pk); + sig->pubkey_algo = pk->pubkey_algo; + if (timestamp) + sig->timestamp = timestamp; + else + sig->timestamp = make_timestamp(); + if (duration) + sig->expiredate = sig->timestamp + duration; + sig->sig_class = sigclass; - if (gcry_md_copy (&md, hash)) - BUG (); + if (gcry_md_copy (&md, hash)) + BUG (); + + if (sig->version >= 4) + { + build_sig_subpkt_from_sig (sig); + mk_notation_policy_etc (sig, pk, NULL); + } + + hash_sigversion_to_magic (md, sig); + gcry_md_final (md); - if (sig->version >= 4) - { - build_sig_subpkt_from_sig (sig); - mk_notation_policy_etc (sig, NULL, sk); - } - - hash_sigversion_to_magic (md, sig); - gcry_md_final (md); - - rc = do_sign( sk, sig, md, hash_for (sk) ); - gcry_md_close (md); - if( !rc ) { /* and write it */ - PACKET pkt; - - init_packet(&pkt); - pkt.pkttype = PKT_SIGNATURE; - pkt.pkt.signature = sig; - rc = build_packet (out, &pkt); - if (!rc && is_status_enabled()) { - print_status_sig_created ( sk, sig, status_letter); - } - free_packet (&pkt); - if (rc) - log_error ("build signature packet failed: %s\n", - g10_errstr(rc) ); + rc = do_sign (pk, sig, md, hash_for (pk)); + gcry_md_close (md); + if (!rc) + { + /* Write the packet. */ + PACKET pkt; + + init_packet (&pkt); + pkt.pkttype = PKT_SIGNATURE; + pkt.pkt.signature = sig; + rc = build_packet (out, &pkt); + if (!rc && is_status_enabled()) + print_status_sig_created (pk, sig, status_letter); + free_packet (&pkt); + if (rc) + log_error ("build signature packet failed: %s\n", gpg_strerror (rc)); } - if( rc ) - return rc;; + if (rc) + return rc; } - - return 0; + + return 0; } + /**************** * Sign the files whose names are in FILENAME. * If DETACHED has the value true, @@ -863,10 +871,10 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr, for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - if (sk_rover->sk->pubkey_algo == PUBKEY_ALGO_DSA) + if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_DSA) { int temp_hashlen = gcry_mpi_get_nbits - (sk_rover->sk->skey[1])+7/8; + (sk_rover->pk->pkey[1])+7/8; /* Pick a hash that is large enough for our largest q */ @@ -874,9 +882,10 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr, if (hint.digest_lengthsk->is_protected - && sk_rover->sk->protect.s2k.mode == 1002) - smartcard = 1; + /* FIXME: need toall gpg-agent */ + /* else if (sk_rover->pk->is_protected */ + /* && sk_rover->pk->protect.s2k.mode == 1002) */ + /* smartcard = 1; */ } /* Current smartcards only do 160-bit hashes. If we have @@ -893,10 +902,8 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr, } } - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk = sk_rover->sk; - gcry_md_enable (mfx.md, hash_for(sk)); - } + for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) + gcry_md_enable (mfx.md, hash_for (sk_rover->pk)); if( !multifile ) iobuf_push_filter( inp, md_filter, &mfx ); @@ -1116,15 +1123,16 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile ) iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----" LF ); - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk = sk_rover->sk; - if( hash_for(sk) == DIGEST_ALGO_MD5 ) - only_md5 = 1; - else { + for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) + { + if (hash_for (sk_rover->pk) == DIGEST_ALGO_MD5) + only_md5 = 1; + else + { only_md5 = 0; break; - } - } + } + } if( !(old_style && only_md5) ) { const char *s; @@ -1134,8 +1142,7 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile ) memset( hashs_seen, 0, sizeof hashs_seen ); iobuf_writestr(out, "Hash: " ); for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk = sk_rover->sk; - int i = hash_for(sk); + int i = hash_for (sk_rover->pk); if( !hashs_seen[ i & 0xff ] ) { s = gcry_md_algo_name ( i ); @@ -1159,10 +1166,9 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile ) if ( gcry_md_open (&textmd, 0, 0) ) BUG (); - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk = sk_rover->sk; - gcry_md_enable (textmd, hash_for(sk)); - } + for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) + gcry_md_enable (textmd, hash_for(sk_rover->pk)); + if ( DBG_HASHING ) gcry_md_start_debug ( textmd, "clearsign" ); @@ -1288,10 +1294,8 @@ sign_symencrypt_file (const char *fname, strlist_t locusr) if ( DBG_HASHING ) gcry_md_start_debug (mfx.md, "symc-sign"); - for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { - PKT_secret_key *sk = sk_rover->sk; - gcry_md_enable (mfx.md, hash_for (sk)); - } + for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) + gcry_md_enable (mfx.md, hash_for (sk_rover->pk)); iobuf_push_filter (inp, md_filter, &mfx); @@ -1376,7 +1380,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr) int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, - PKT_secret_key *sk, + PKT_public_key *pksk, int sigclass, int digest_algo, int sigversion, u32 timestamp, u32 duration, int (*mksubpkt)(PKT_signature *, void *), void *opaque @@ -1393,8 +1397,8 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, if (opt.force_v4_certs) sigversion = 4; - if (sigversion < sk->version) - sigversion = sk->version; + if (sigversion < pksk->version) + sigversion = pksk->version; /* If you are making a signature on a v4 key using your v3 key, it doesn't make sense to generate a v3 sig. After all, no v3-only @@ -1417,11 +1421,11 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, if(opt.cert_digest_algo) digest_algo=opt.cert_digest_algo; - else if(sk->pubkey_algo==PUBKEY_ALGO_RSA + else if(pksk->pubkey_algo==PUBKEY_ALGO_RSA && pk->version<4 && sigversion<4) digest_algo = DIGEST_ALGO_MD5; - else if(sk->pubkey_algo==PUBKEY_ALGO_DSA) - digest_algo = match_dsa_hash (gcry_mpi_get_nbits (sk->skey[1])/8); + else if(pksk->pubkey_algo==PUBKEY_ALGO_DSA) + digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8); else digest_algo = DIGEST_ALGO_SHA1; } @@ -1447,8 +1451,8 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, sig->version = sigversion; sig->flags.exportable=1; sig->flags.revocable=1; - keyid_from_sk( sk, sig->keyid ); - sig->pubkey_algo = sk->pubkey_algo; + keyid_from_pk (pksk, sig->keyid); + sig->pubkey_algo = pksk->pubkey_algo; sig->digest_algo = digest_algo; if(timestamp) sig->timestamp=timestamp; @@ -1460,7 +1464,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, if( sig->version >= 4 ) { build_sig_subpkt_from_sig( sig ); - mk_notation_policy_etc( sig, pk, sk ); + mk_notation_policy_etc (sig, pk, pksk); } /* Crucial that the call to mksubpkt comes LAST before the calls @@ -1473,10 +1477,10 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, hash_sigversion_to_magic (md, sig); gcry_md_final (md); - rc = complete_sig( sig, sk, md ); + rc = complete_sig (sig, pksk, md); } - gcry_md_close ( md ); + gcry_md_close (md); if( rc ) free_seckey_enc( sig ); else @@ -1497,7 +1501,7 @@ update_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, - PKT_secret_key *sk, + PKT_public_key *pksk, int (*mksubpkt)(PKT_signature *, void *), void *opaque ) { @@ -1505,7 +1509,7 @@ update_keysig_packet( PKT_signature **ret_sig, int rc=0; gcry_md_hd_t md; - if ((!orig_sig || !pk || !sk) + if ((!orig_sig || !pk || !pksk) || (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid) || (orig_sig->sig_class == 0x18 && !subpk)) return G10ERR_GENERAL; @@ -1556,7 +1560,7 @@ update_keysig_packet( PKT_signature **ret_sig, hash_sigversion_to_magic (md, sig); gcry_md_final (md); - rc = complete_sig( sig, sk, md ); + rc = complete_sig (sig, pksk, md); } gcry_md_close (md); diff --git a/g10/skclist.c b/g10/skclist.c index 70b375aa3..fd677eba3 100644 --- a/g10/skclist.c +++ b/g10/skclist.c @@ -1,5 +1,6 @@ /* skclist.c - Build a list of secret keys - * Copyright (C) 1998, 1999, 2000, 2001, 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2006, + * 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -33,224 +34,246 @@ #include "i18n.h" #include "cipher.h" -#ifndef GCRYCTL_FAKED_RANDOM_P -#define GCRYCTL_FAKED_RANDOM_P 51 -#endif /* Return true if Libgcrypt's RNG is in faked mode. */ int random_is_faked (void) { - return !!gcry_control ( GCRYCTL_FAKED_RANDOM_P, 0); + return !!gcry_control (GCRYCTL_FAKED_RANDOM_P, 0); } - void -release_sk_list( SK_LIST sk_list ) +release_sk_list (SK_LIST sk_list) { - SK_LIST sk_rover; + SK_LIST sk_rover; - for( ; sk_list; sk_list = sk_rover ) { - sk_rover = sk_list->next; - free_secret_key( sk_list->sk ); - xfree( sk_list ); + for (; sk_list; sk_list = sk_rover) + { + sk_rover = sk_list->next; + if (sk_list->pk) + free_public_key (sk_list->pk); + xfree (sk_list); } } /* Check that we are only using keys which don't have * the string "(insecure!)" or "not secure" or "do not use" - * in one of the user ids - */ + * in one of the user ids. */ static int -is_insecure( PKT_secret_key *sk ) +is_insecure (PKT_public_key *pk) { - u32 keyid[2]; - KBNODE node = NULL, u; - int insecure = 0; + u32 keyid[2]; + KBNODE node = NULL, u; + int insecure = 0; - keyid_from_sk( sk, keyid ); - node = get_pubkeyblock( keyid ); - for ( u = node; u; u = u->next ) { - if ( u->pkt->pkttype == PKT_USER_ID ) { - PKT_user_id *id = u->pkt->pkt.user_id; - if ( id->attrib_data ) - continue; /* skip attribute packets */ - if ( strstr( id->name, "(insecure!)" ) - || strstr( id->name, "not secure" ) - || strstr( id->name, "do not use" ) - || strstr( id->name, "(INSECURE!)" ) ) { - insecure = 1; - break; - } - } + keyid_from_pk (pk, keyid); + node = get_pubkeyblock (keyid); + for (u = node; u; u = u->next) + { + if (u->pkt->pkttype == PKT_USER_ID) + { + PKT_user_id *id = u->pkt->pkt.user_id; + if (id->attrib_data) + continue; /* skip attribute packets */ + if (strstr (id->name, "(insecure!)") + || strstr (id->name, "not secure") + || strstr (id->name, "do not use") + || strstr (id->name, "(INSECURE!)")) + { + insecure = 1; + break; + } + } } - release_kbnode( node ); - - return insecure; + release_kbnode (node); + + return insecure; } static int -key_present_in_sk_list(SK_LIST sk_list, PKT_secret_key *sk) +key_present_in_sk_list (SK_LIST sk_list, PKT_public_key *pk) { - for (; sk_list; sk_list = sk_list->next) { - if ( !cmp_secret_keys(sk_list->sk, sk) ) - return 0; + for (; sk_list; sk_list = sk_list->next) + { + if (!cmp_public_keys (sk_list->pk, pk)) + return 0; } - return -1; + return -1; } static int is_duplicated_entry (strlist_t list, strlist_t item) { - for(; list && list != item; list = list->next) { - if ( !strcmp (list->d, item->d) ) - return 1; + for (; list && list != item; list = list->next) + { + if (!strcmp (list->d, item->d)) + return 1; } - return 0; + return 0; } -int -build_sk_list( strlist_t locusr, SK_LIST *ret_sk_list, - int unlock, unsigned int use ) +/* FIXME: We ignore the UNLOCK flag - should not be needed anymore. */ +gpg_error_t +build_sk_list (strlist_t locusr, SK_LIST *ret_sk_list, + int unlock, unsigned int use) { - SK_LIST sk_list = NULL; - int rc; + gpg_error_t err; + SK_LIST sk_list = NULL; - if( !locusr ) - { /* use the default one */ - PKT_secret_key *sk; + if (!locusr) /* No user ids given - use the default key. */ + { + PKT_public_key *pk; - sk = xmalloc_clear( sizeof *sk ); - sk->req_usage = use; - if( (rc = get_seckey_byname( sk, NULL, unlock )) ) { - free_secret_key( sk ); sk = NULL; - log_error("no default secret key: %s\n", g10_errstr(rc) ); - write_status_text (STATUS_INV_SGNR, - get_inv_recpsgnr_code (GPG_ERR_NO_SECKEY)); + pk = xmalloc_clear (sizeof *pk); + pk->req_usage = use; + if ((err = getkey_byname (NULL, pk, NULL, 1, NULL))) + { + free_public_key (pk); + pk = NULL; + log_error ("no default secret key: %s\n", gpg_strerror (err)); + write_status_text (STATUS_INV_SGNR, get_inv_recpsgnr_code (err)); } - else if( !(rc=openpgp_pk_test_algo2 (sk->pubkey_algo, use)) ) - { - SK_LIST r; - - if( random_is_faked() && !is_insecure( sk ) ) - { - log_info(_("key is not flagged as insecure - " - "can't use it with the faked RNG!\n")); - free_secret_key( sk ); sk = NULL; - write_status_text (STATUS_INV_SGNR, - get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED)); - } - else - { - r = xmalloc( sizeof *r ); - r->sk = sk; sk = NULL; - r->next = sk_list; - r->mark = 0; - sk_list = r; - } - } - else - { - free_secret_key( sk ); sk = NULL; - log_error("invalid default secret key: %s\n", g10_errstr(rc) ); - write_status_text (STATUS_INV_SGNR, get_inv_recpsgnr_code (rc)); - } - } - else { - strlist_t locusr_orig = locusr; - for(; locusr; locusr = locusr->next ) { - PKT_secret_key *sk; - - rc = 0; - /* Do an early check agains duplicated entries. However this - * won't catch all duplicates because the user IDs may be - * specified in different ways. - */ - if ( is_duplicated_entry ( locusr_orig, locusr ) ) - { - log_info (_("skipped \"%s\": duplicated\n"), locusr->d ); - continue; - } - sk = xmalloc_clear( sizeof *sk ); - sk->req_usage = use; - if( (rc = get_seckey_byname( sk, locusr->d, 0 )) ) - { - free_secret_key( sk ); sk = NULL; - log_error(_("skipped \"%s\": %s\n"), - locusr->d, g10_errstr(rc) ); - write_status_text_and_buffer - (STATUS_INV_SGNR, get_inv_recpsgnr_code (rc), - locusr->d, strlen (locusr->d), -1); - } - else if ( key_present_in_sk_list(sk_list, sk) == 0) { - free_secret_key(sk); sk = NULL; - log_info(_("skipped: secret key already present\n")); - } - else if ( unlock && (rc = check_secret_key( sk, 0 )) ) - { - free_secret_key( sk ); sk = NULL; - log_error(_("skipped \"%s\": %s\n"), - locusr->d, g10_errstr(rc) ); - write_status_text_and_buffer - (STATUS_INV_SGNR, get_inv_recpsgnr_code (rc), - locusr->d, strlen (locusr->d), -1); - } - else if( !(rc=openpgp_pk_test_algo2 (sk->pubkey_algo, use)) ) { - SK_LIST r; - - if( sk->version == 4 && (use & PUBKEY_USAGE_SIG) - && sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) - { - log_info(_("skipped \"%s\": %s\n"),locusr->d, - _("this is a PGP generated Elgamal key which" - " is not secure for signatures!")); - free_secret_key( sk ); sk = NULL; - write_status_text_and_buffer - (STATUS_INV_SGNR, - get_inv_recpsgnr_code (GPG_ERR_WRONG_KEY_USAGE), - locusr->d, strlen (locusr->d), -1); - } - else if( random_is_faked() && !is_insecure( sk ) ) { - log_info(_("key is not flagged as insecure - " - "can't use it with the faked RNG!\n")); - free_secret_key( sk ); sk = NULL; - write_status_text_and_buffer - (STATUS_INV_SGNR, - get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED), - locusr->d, strlen (locusr->d), -1); - } - else { - r = xmalloc( sizeof *r ); - r->sk = sk; sk = NULL; - r->next = sk_list; - r->mark = 0; - sk_list = r; - } + else if ((err = openpgp_pk_test_algo2 (pk->pubkey_algo, use))) + { + free_public_key (pk); + pk = NULL; + log_error ("invalid default secret key: %s\n", gpg_strerror (err)); + write_status_text (STATUS_INV_SGNR, get_inv_recpsgnr_code (err)); + } + else + { + SK_LIST r; + + if (random_is_faked () && !is_insecure (pk)) + { + log_info (_("key is not flagged as insecure - " + "can't use it with the faked RNG!\n")); + free_public_key (pk); + pk = NULL; + write_status_text (STATUS_INV_SGNR, + get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED)); } - else { - free_secret_key( sk ); sk = NULL; - log_error("skipped \"%s\": %s\n", locusr->d, g10_errstr(rc) ); - write_status_text_and_buffer - (STATUS_INV_SGNR, get_inv_recpsgnr_code (rc), - locusr->d, strlen (locusr->d), -1); + else + { + r = xmalloc (sizeof *r); + r->pk = pk; + pk = NULL; + r->next = sk_list; + r->mark = 0; + sk_list = r; + } + } + } + else /* Check the given user ids. */ + { + strlist_t locusr_orig = locusr; + + for (; locusr; locusr = locusr->next) + { + PKT_public_key *pk; + + err = 0; + /* Do an early check against duplicated entries. However + * this won't catch all duplicates because the user IDs may + * be specified in different ways. */ + if (is_duplicated_entry (locusr_orig, locusr)) + { + log_info (_("skipped \"%s\": duplicated\n"), locusr->d); + continue; + } + pk = xmalloc_clear (sizeof *pk); + pk->req_usage = use; + if ((err = getkey_byname (NULL, pk, locusr->d, 1, NULL))) + { + free_public_key (pk); + pk = NULL; + log_error (_("skipped \"%s\": %s\n"), + locusr->d, gpg_strerror (err)); + write_status_text_and_buffer + (STATUS_INV_SGNR, get_inv_recpsgnr_code (err), + locusr->d, strlen (locusr->d), -1); + } + else if (!key_present_in_sk_list (sk_list, pk)) + { + free_public_key (pk); + pk = NULL; + log_info (_("skipped: secret key already present\n")); + } + /* Fixme: We could change the next test by a call to gpg-agent which + would then cache the passphrase. */ + /* else if (unlock && (rc = check_secret_key (sk, 0))) */ + /* { */ + /* free_secret_key (sk); */ + /* sk = NULL; */ + /* log_error (_("skipped \"%s\": %s\n"), */ + /* locusr->d, g10_errstr (rc)); */ + /* write_status_text_and_buffer */ + /* (STATUS_INV_SGNR, get_inv_recpsgnr_code (rc), */ + /* locusr->d, strlen (locusr->d), -1); */ + /* } */ + else if ((err = openpgp_pk_test_algo2 (pk->pubkey_algo, use))) + { + free_public_key (pk); + pk = NULL; + log_error ("skipped \"%s\": %s\n", locusr->d, gpg_strerror (err)); + write_status_text_and_buffer + (STATUS_INV_SGNR, get_inv_recpsgnr_code (err), + locusr->d, strlen (locusr->d), -1); + } + else + { + SK_LIST r; + + if (pk->version == 4 && (use & PUBKEY_USAGE_SIG) + && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E) + { + log_info (_("skipped \"%s\": %s\n"), locusr->d, + _("this is a PGP generated Elgamal key which" + " is not secure for signatures!")); + free_public_key (pk); + pk = NULL; + write_status_text_and_buffer + (STATUS_INV_SGNR, + get_inv_recpsgnr_code (GPG_ERR_WRONG_KEY_USAGE), + locusr->d, strlen (locusr->d), -1); + } + else if (random_is_faked () && !is_insecure (pk)) + { + log_info (_("key is not flagged as insecure - " + "can't use it with the faked RNG!\n")); + free_public_key (pk); + pk = NULL; + write_status_text_and_buffer + (STATUS_INV_SGNR, + get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED), + locusr->d, strlen (locusr->d), -1); + } + else + { + r = xmalloc (sizeof *r); + r->pk = pk; + pk = NULL; + r->next = sk_list; + r->mark = 0; + sk_list = r; + } } } } - - if( !rc && !sk_list ) { - log_error("no valid signators\n"); - write_status_text (STATUS_NO_SGNR, "0"); - rc = G10ERR_NO_USER_ID; + if (!err && !sk_list) + { + log_error ("no valid signators\n"); + write_status_text (STATUS_NO_SGNR, "0"); + err = gpg_error (GPG_ERR_NO_USER_ID); } - - if( rc ) - release_sk_list( sk_list ); - else - *ret_sk_list = sk_list; - return rc; + + if (err) + release_sk_list (sk_list); + else + *ret_sk_list = sk_list; + return err; } - diff --git a/jnlib/w32-gettext.c b/jnlib/w32-gettext.c index 834b2aa17..3060a96e2 100644 --- a/jnlib/w32-gettext.c +++ b/jnlib/w32-gettext.c @@ -1,6 +1,6 @@ /* w32-gettext.h - A simple gettext implementation for Windows targets. Copyright (C) 1995, 1996, 1997, 1999, 2005, 2007, - 2008 Free Software Foundation, Inc. + 2008, 2010 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License @@ -612,6 +612,7 @@ my_nl_locale_name (const char *categoryname) /* Let the user override the system settings through environment variables, as on POSIX systems. */ +#ifndef HAVE_W32CE_SYSTEM retval = getenv ("LC_ALL"); if (retval != NULL && retval[0] != '\0') return retval; @@ -621,9 +622,14 @@ my_nl_locale_name (const char *categoryname) retval = getenv ("LANG"); if (retval != NULL && retval[0] != '\0') return retval; +#endif /*!HAVE_W32CE_SYSTEM*/ /* Use native Win32 API locale ID. */ +#ifdef HAVE_W32CE_SYSTEM + lcid = GetSystemDefaultLCID (); +#else lcid = GetThreadLocale (); +#endif /* Strip off the sorting rules, keep only the language part. */ langid = LANGIDFROMLCID (lcid); @@ -1116,14 +1122,15 @@ struct loaded_domain char *data_native; /* Data mapped to the native version of the string. (Allocated along with DATA). */ int must_swap; - uint32_t nstrings; - uint32_t *mapped; /* 0 := Not mapped (original utf8). + uint32_t nstrings; /* Number of strings. */ + uint32_t *mapped; /* Array of mapping indicators: + 0 := Not mapped (original utf8). 1 := Mapped to native encoding in overflow space. - >=2 := Mapped to native encoding. The values + >=2 := Mapped to native encoding. The value gives the length of the mapped string. - becuase the 0 is included and an empty - string is not allowed we will enver get - values 0 and 1. */ + Because the terminating nul is included + in the length and an empty string is + not allowed, values are always > 1. */ struct overflow_space_s *overflow_space; struct string_desc *orig_tab; struct string_desc *trans_tab; @@ -1366,7 +1373,7 @@ bindtextdomain (const char *domainname, const char *dirname) catval = NULL; catval_full = my_nl_locale_name ("LC_MESSAGES"); - /* Normally, we would have to loop over all returned locales, and + /* Normally we would have to loop over all returned locales and search for the right file. See gettext intl/dcigettext.c for all the gory details. Here, we only support the basic category, and ignore everything else. */ @@ -1389,8 +1396,8 @@ bindtextdomain (const char *domainname, const char *dirname) /* Now build the filename string. The complete filename is this: DIRNAME + \ + CATVAL + \LC_MESSAGES\ + DOMAINNAME + .mo */ { - int len = strlen (dirname) + 1 + strlen (catval) + 13 - + strlen (domainname) + 3 + 1; + int len = (strlen (dirname) + 1 + strlen (catval) + 13 + + strlen (domainname) + 3 + 1); char *p; fname = jnlib_malloc (len); @@ -1497,9 +1504,9 @@ get_string (struct loaded_domain *domain, uint32_t idx, else { /* There is not enough space for the translation (or for - whatever reason an empry string is used): Store it in the + whatever reason an empty string is used): Store it in the overflow_space and mark that in the mapped array. - Because UTF-8 strings are in general longer than the + Because UTF-8 strings are in general shorter than the Windows 2 byte encodings, we expect that this won't happen too often (if at all) and thus we use a linked list to manage this space. */ diff --git a/sm/keylist.c b/sm/keylist.c index e323b2740..feb117d10 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -1428,7 +1428,7 @@ list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp, if (p) { rc = gpgsm_agent_havekey (ctrl, p); - if (!rc) + if (!rc) have_secret = 1; else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY) goto leave; diff --git a/tools/ChangeLog b/tools/ChangeLog index efb0478e1..2008882a4 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2010-01-10 Werner Koch + + * symcryptrun.c (utmp.h): Remove header; it is not used. + 2009-12-18 Werner Koch * applygnupgdefaults (errorfile): Use mktemp. Fixes bug#1146. diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index b46990cd2..7eeff97a1 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -74,7 +74,6 @@ #ifdef HAVE_PTY_H #include #endif -#include #include #ifdef HAVE_LOCALE_H #include