diff options
Diffstat (limited to 'g10/keyedit.c')
-rw-r--r-- | g10/keyedit.c | 282 |
1 files changed, 76 insertions, 206 deletions
diff --git a/g10/keyedit.c b/g10/keyedit.c index 1686fa6e0..ee411016e 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -30,6 +30,7 @@ # include <readline/readline.h> #endif +#define JNLIB_NEED_LOG_LOGV #include "gpg.h" #include "options.h" #include "packet.h" @@ -1124,44 +1125,63 @@ leave: /* - * Change the passphrase of the primary and all secondary keys. - * We use only one passphrase for all keys. + * Change the passphrase of the primary and all secondary keys. Note + * that it is common to use only one passphrase for the primary and + * all subkeys. However, this is now (since GnuPG 2.1) all up to the + * gpg-agent. Returns 0 on success or an error code. */ -static int -change_passphrase (KBNODE keyblock, int *r_err) +static gpg_error_t +change_passphrase (ctrl_t ctrl, kbnode_t keyblock) { - int rc = 0; - int changed = 0; - KBNODE node; - PKT_public_key *pksk; - char *passphrase = NULL; - int no_primary_secrets = 0; + gpg_error_t err; + kbnode_t node; + PKT_public_key *pk; int any; + u32 keyid[2], subid[2]; + char *hexgrip = NULL; + char *cache_nonce = NULL; + char *passwd_nonce = NULL; node = find_kbnode (keyblock, PKT_PUBLIC_KEY); if (!node) { log_error ("Oops; public key missing!\n"); + err = gpg_error (GPG_ERR_INTERNAL); goto leave; } - pksk = node->pkt->pkt.public_key; + pk = node->pkt->pkt.public_key; + keyid_from_pk (pk, keyid); + /* Check whether it is likely that we will be able to change the + passphrase for any subkey. */ for (any = 0, node = keyblock; node; node = node->next) { if (node->pkt->pkttype == PKT_PUBLIC_KEY || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) { - log_debug ("FIXME\n"); - /* PKT_public_key *tmpsk = node->pkt->pkt.public_key; */ - /* if (!(tmpsk->is_protected */ - /* && (tmpsk->protect.s2k.mode == 1001 */ - /* || tmpsk->protect.s2k.mode == 1002))) */ - /* { */ - /* any = 1; */ - /* break; */ - /* } */ + char *serialno; + + pk = node->pkt->pkt.public_key; + keyid_from_pk (pk, subid); + + xfree (hexgrip); + err = hexkeygrip_from_pk (pk, &hexgrip); + if (err) + goto leave; + err = agent_get_keyinfo (ctrl, hexgrip, &serialno); + if (!err && serialno) + ; /* Key on card. */ + else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) + ; /* Maybe stub key. */ + else if (!err) + any = 1; /* Key is known. */ + else + log_error ("key %s: error getting keyinfo from agent: %s\n", + keystr_with_sub (keyid, subid), gpg_strerror (err)); + xfree (serialno); } } + err = 0; if (!any) { tty_printf (_("Key has only stub or on-card key items - " @@ -1169,162 +1189,43 @@ change_passphrase (KBNODE keyblock, int *r_err) goto leave; } - log_debug ("FIXME\n"); - /* See how to handle this key. */ - /* switch (is_secret_key_protected (pksk)) */ - /* { */ - /* case -1: */ - /* rc = G10ERR_PUBKEY_ALGO; */ - /* break; */ - /* case 0: */ - /* tty_printf (_("This key is not protected.\n")); */ - /* break; */ - /* default: */ - /* if (sk->protect.s2k.mode == 1001) */ - /* { */ - /* tty_printf (_("Secret parts of key are not available.\n")); */ - /* no_primary_secrets = 1; */ - /* } */ - /* else if (sk->protect.s2k.mode == 1002) */ - /* { */ - /* tty_printf (_("Secret parts of key are stored on-card.\n")); */ - /* no_primary_secrets = 1; */ - /* } */ - /* else */ - /* { */ - /* u32 keyid[2]; */ - - /* tty_printf (_("Key is protected.\n")); */ - - /* /\* Clear the passphrase cache so that the user is required */ - /* to enter the old passphrase. *\/ */ - /* keyid_from_pk (pksk, keyid); */ - /* passphrase_clear_cache (keyid, NULL, 0); */ - - /* /\* rc = check_secret_key( sk, 0 ); *\/ */ - /* /\* if( !rc ) *\/ */ - /* /\* passphrase = get_last_passphrase(); *\/ */ - /* } */ - /* break; */ - /* } */ - - /* Unprotect all subkeys (use the supplied passphrase or ask) */ - for (node = keyblock; !rc && node; node = node->next) - { - if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) - { - log_debug ("FIXME\n"); - /* PKT_pubic_key *subsk = node->pkt->pkt.public_key; */ - /* if (!(subsk->is_protected */ - /* && (subsk->protect.s2k.mode == 1001 */ - /* || subsk->protect.s2k.mode == 1002))) */ - /* { */ - /* set_next_passphrase (passphrase); */ - /* /\* rc = check_secret_key( subsk, 0 ); *\/ */ - /* /\* if( !rc && !passphrase ) *\/ */ - /* /\* passphrase = get_last_passphrase(); *\/ */ - /* } */ - } - } - - if (rc) - tty_printf (_("Can't edit this key: %s\n"), g10_errstr (rc)); - else + /* Change the passphrase for all keys. */ + for (any = 0, node = keyblock; node; node = node->next) { - DEK *dek = NULL; - STRING2KEY *s2k = xmalloc_secure (sizeof *s2k); - const char *errtext = NULL; - - tty_printf (_("Enter the new passphrase for this secret key.\n\n")); - - set_next_passphrase (NULL); - for (;;) - { - int canceled; - - s2k->mode = opt.s2k_mode; - s2k->hash_algo = S2K_DIGEST_ALGO; - dek = passphrase_to_dek (NULL, 0, opt.s2k_cipher_algo, - s2k, 2, errtext, &canceled); - if (!dek && canceled) - { - rc = GPG_ERR_CANCELED; - break; - } - else if (!dek) - { - errtext = N_("passphrase not correctly repeated; try again"); - tty_printf ("%s.\n", _(errtext)); - } - else if (!dek->keylen) - { - rc = 0; - tty_printf (_("You don't want a passphrase -" - " this is probably a *bad* idea!\n\n")); - if (cpr_get_answer_is_yes - ("change_passwd.empty.okay", - _("Do you really want to do this? (y/N) "))) - { - changed++; - break; - } - } - else - { /* okay */ - rc = 0; - if (!no_primary_secrets) - { - /* sk->protect.algo = dek->algo; */ - /* sk->protect.s2k = *s2k; */ - rc = 0; - /* rc = protect_secret_key( sk, dek ); */ - } - for (node = keyblock; !rc && node; node = node->next) - { - if (node->pkt->pkttype == PKT_SECRET_SUBKEY) - { - log_debug ("FIXME\n"); -/* PKT_secret_key *subsk = node->pkt->pkt.secret_key; */ -/* if (!(subsk->is_protected */ -/* && (subsk->protect.s2k.mode == 1001 */ -/* || subsk->protect.s2k.mode == 1002))) */ -/* { */ -/* subsk->protect.algo = dek->algo; */ -/* subsk->protect.s2k = *s2k; */ -/* #warning fixme */ -/* rc = 0; */ -/* /\* rc = protect_secret_key( subsk, dek ); *\/ */ -/* } */ - } - } - if (rc) - log_error ("protect_secret_key failed: %s\n", - g10_errstr (rc)); - else - { - u32 keyid[2]; + if (node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) + { + char *desc; - /* Clear the cahce again so that the user is - required to enter the new passphrase at the - next operation. */ - /* FIXME keyid_from_sk (sk, keyid); */ - passphrase_clear_cache (keyid, NULL, 0); + pk = node->pkt->pkt.public_key; + keyid_from_pk (pk, subid); - changed++; - } - break; - } - } - xfree (s2k); - xfree (dek); + xfree (hexgrip); + err = hexkeygrip_from_pk (pk, &hexgrip); + if (err) + goto leave; + + desc = gpg_format_keydesc (pk, 0, 1); + err = agent_passwd (ctrl, hexgrip, desc, &cache_nonce, &passwd_nonce); + xfree (desc); + + if (err) + log_log ((gpg_err_code (err) == GPG_ERR_CANCELED + || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED) + ? JNLIB_LOG_INFO : JNLIB_LOG_ERROR, + _("key %s: error changing passphrase: %s\n"), + keystr_with_sub (keyid, subid), + gpg_strerror (err)); + if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED) + break; + } } -leave: - xfree (passphrase); - set_next_passphrase (NULL); - if (r_err) - *r_err = rc; - return changed && !rc; + leave: + xfree (hexgrip); + xfree (cache_nonce); + xfree (passwd_nonce); + return err; } @@ -2184,7 +2085,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, break; case cmdPASSWD: - change_passphrase (keyblock, NULL); + change_passphrase (ctrl, keyblock); break; case cmdTRUST: @@ -2361,13 +2262,10 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, /* Change the passphrase of the secret key identified by USERNAME. */ void -keyedit_passwd (const char *username) +keyedit_passwd (ctrl_t ctrl, const char *username) { 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; pk = xtrycalloc (1, sizeof *pk); @@ -2376,44 +2274,16 @@ keyedit_passwd (const char *username) 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 = NULL /*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); + err = getkey_byname (NULL, pk, username, 1, &keyblock); if (err) goto leave; - if (!change_passphrase (keyblock, &err)) - goto leave; - - err = keydb_update_keyblock (kdh, keyblock); - if (err) - log_error (_("update secret failed: %s\n"), gpg_strerror (err)); + err = change_passphrase (ctrl, keyblock); 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", |