From 243791190396cbc9f256afd92265519210a7e2ae Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 11 Jan 2010 16:05:26 +0000 Subject: [PATCH] Implement command --passwd for GPG. --- NEWS | 2 ++ doc/gpg.texi | 8 ++++++ g10/ChangeLog | 13 +++++++++ g10/gpg.c | 46 ++++++++++++++++++++------------ g10/keyedit.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++- g10/main.h | 1 + g10/options.h | 2 +- g10/passphrase.c | 2 +- 8 files changed, 123 insertions(+), 19 deletions(-) diff --git a/NEWS b/NEWS index 470c20164..ced6b5c2b 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ Noteworthy changes in version 2.0.15 (unreleased) ------------------------------------------------- + * New command --passwd for GPG. + Noteworthy changes in version 2.0.14 (2009-12-21) ------------------------------------------------- diff --git a/doc/gpg.texi b/doc/gpg.texi index d053ed677..39529888e 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -586,6 +586,7 @@ Present a menu which enables you to do most of the key management related tasks. It expects the specification of a key on the command line. + @c ******** Begin Edit-key Options ********** @table @asis @@ -888,6 +889,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} in the edit key menu. +@end ifclear @end table diff --git a/g10/ChangeLog b/g10/ChangeLog index ca1d2ae8e..fb9c9b573 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,16 @@ +2010-01-11 Werner Koch + + * gpg.c: Add option --passwd. + (aPasswd): New. + (main): Implement. + * keyedit.c (keyedit_passwd): New. + + * gpg.c (oPasswd, oPasswdFD, oPasswdFile, oPasswdRepeat): Change + to oPassphrase, oPassphraseFD, oPassphraseFile, oPassphraseRepeat. + * options.h (struct): s/passwd_repeat/passphrase_repeat/. + * gpg.c (main): Ditto. + * passphrase.c (passphrase_to_dek_ext): Ditto. + 2009-12-21 Werner Koch * gpg.c (main): Add dummy options --skip-hidden-recipients and no diff --git a/g10/gpg.c b/g10/gpg.c index 8fea30be8..f22904ef0 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -1,6 +1,6 @@ /* gpg.c - The GnuPG utility (main for gpg) * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + * 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -146,6 +146,7 @@ enum cmd_and_opt_values aCardStatus, aCardEdit, aChangePIN, + aPasswd, aServer, oTextmode, @@ -207,10 +208,10 @@ enum cmd_and_opt_values oCompressLevel, oBZ2CompressLevel, oBZ2DecompressLowmem, - oPasswd, - oPasswdFD, - oPasswdFile, - oPasswdRepeat, + oPassphrase, + oPassphraseFD, + oPassphraseFile, + oPassphraseRepeat, oCommandFD, oCommandFile, oQuickRandom, @@ -389,6 +390,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_c (oFingerprint, "fingerprint", N_("list keys and fingerprints")), ARGPARSE_c (aListSecretKeys, "list-secret-keys", N_("list secret keys")), ARGPARSE_c (aKeygen, "gen-key", N_("generate a new key pair")), + ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")), ARGPARSE_c (aDeleteKeys,"delete-keys", N_("remove keys from the public keyring")), ARGPARSE_c (aDeleteSecretKeys, "delete-secret-keys", @@ -397,7 +399,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_c (aLSignKey, "lsign-key" ,N_("sign a key locally")), ARGPARSE_c (aEditKey, "edit-key" ,N_("sign or edit a key")), ARGPARSE_c (aEditKey, "key-edit" ,"@"), - ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")), + ARGPARSE_c (aPasswd, "passwd", N_("change a passphrase")), ARGPARSE_c (aDesigRevoke, "desig-revoke","@" ), ARGPARSE_c (aExport, "export" , N_("export keys") ), ARGPARSE_c (aSendKeys, "send-keys" , N_("export keys to a key server") ), @@ -599,10 +601,10 @@ static ARGPARSE_OPTS opts[] = { "delete-secret-and-public-keys", "@"), ARGPARSE_c (aRebuildKeydbCaches, "rebuild-keydb-caches", "@"), - ARGPARSE_s_s (oPasswd, "passphrase", "@"), - ARGPARSE_s_i (oPasswdFD, "passphrase-fd", "@"), - ARGPARSE_s_s (oPasswdFile, "passphrase-file", "@"), - ARGPARSE_s_i (oPasswdRepeat, "passphrase-repeat", "@"), + ARGPARSE_s_s (oPassphrase, "passphrase", "@"), + ARGPARSE_s_i (oPassphraseFD, "passphrase-fd", "@"), + ARGPARSE_s_s (oPassphraseFile, "passphrase-file", "@"), + ARGPARSE_s_i (oPassphraseRepeat,"passphrase-repeat", "@"), ARGPARSE_s_i (oCommandFD, "command-fd", "@"), ARGPARSE_s_s (oCommandFile, "command-file", "@"), ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"), @@ -628,7 +630,6 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (aListSigs, "list-sig", "@"), /* alias */ ARGPARSE_s_n (aCheckKeys, "check-sig", "@"), /* alias */ ARGPARSE_s_n (oSkipVerify, "skip-verify", "@"), - ARGPARSE_s_n (oSkipVerify, "skip-verify", "@"), ARGPARSE_s_n (oSkipHiddenRecipients, "skip-hidden-recipients", "@"), ARGPARSE_s_n (oNoSkipHiddenRecipients, "no-skip-hidden-recipients", "@"), ARGPARSE_s_n (oCompressKeys, "compress-keys", "@"), @@ -1430,6 +1431,7 @@ check_permissions(const char *path,int item) } +/* Print the OpenPGP defined algo numbers. */ static void print_algo_numbers(int (*checker)(int)) { @@ -1997,7 +1999,7 @@ main (int argc, char **argv) opt.def_sig_expire="0"; opt.def_cert_expire="0"; set_homedir ( default_homedir () ); - opt.passwd_repeat=1; + opt.passphrase_repeat=1; /* Check whether we have a config file on the command line. */ orig_argc = argc; @@ -2179,6 +2181,7 @@ main (int argc, char **argv) case aDeleteSecretKeys: case aDeleteSecretAndPublicKeys: case aDeleteKeys: + case aPasswd: set_cmd (&cmd, pargs.r_opt); greeting=1; break; @@ -2558,16 +2561,16 @@ main (int argc, char **argv) case oCompressLevel: opt.compress_level = pargs.r.ret_int; break; case oBZ2CompressLevel: opt.bz2_compress_level = pargs.r.ret_int; break; case oBZ2DecompressLowmem: opt.bz2_decompress_lowmem=1; break; - case oPasswd: + case oPassphrase: set_passphrase_from_string(pargs.r.ret_str); break; - case oPasswdFD: + case oPassphraseFD: pwfd = translate_sys2libc_fd_int (pargs.r.ret_int, 0); break; - case oPasswdFile: + case oPassphraseFile: pwfd = open_info_file (pargs.r.ret_str, 0, 1); break; - case oPasswdRepeat: opt.passwd_repeat=pargs.r.ret_int; break; + case oPassphraseRepeat: opt.passphrase_repeat=pargs.r.ret_int; break; case oCommandFD: opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0); break; @@ -3621,6 +3624,17 @@ main (int argc, char **argv) xfree(username); break; + case aPasswd: + if (argc != 1) + wrong_args (_("--passwd ")); + else + { + username = make_username (fname); + keyedit_passwd (username); + xfree (username); + } + break; + case aDeleteKeys: case aDeleteSecretKeys: case aDeleteSecretAndPublicKeys: diff --git a/g10/keyedit.c b/g10/keyedit.c index bc79e8fa8..d55cbbfbe 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -1,6 +1,6 @@ /* keyedit.c - keyedit stuff * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - * 2008, 2009 Free Software Foundation, Inc. + * 2008, 2009, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -2299,6 +2299,72 @@ keyedit_menu( const char *username, strlist_t locusr, xfree(answer); } + +/* Change the passphrase of the secret key identified by USERNAME. */ +void +keyedit_passwd (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 keyblock = NULL; + + pk = xtrycalloc (1, sizeof *pk); + if (!pk) + { + err = gpg_error_from_syserror (); + goto leave; + } + err = get_pubkey_byname (NULL, pk, username, NULL, NULL, 1, 1); + if (err) + goto leave; + fingerprint_from_pk (pk, fpr, &fprlen); + while (fprlen < MAX_FINGERPRINT_LEN) + fpr[fprlen++] = 0; + + 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", gpg_err_code (err)); + } +} + + static void tty_print_notations(int indent,PKT_signature *sig) { diff --git a/g10/main.h b/g10/main.h index d46c0ff9f..3a421373a 100644 --- a/g10/main.h +++ b/g10/main.h @@ -213,6 +213,7 @@ int delete_keys( strlist_t names, int secret, int allow_both ); /*-- keyedit.c --*/ void keyedit_menu( const char *username, strlist_t locusr, strlist_t commands, int quiet, int seckey_check ); +void keyedit_passwd (const char *username); void show_basic_key_info (KBNODE keyblock); /*-- keygen.c --*/ diff --git a/g10/options.h b/g10/options.h index a99ca22e8..46f746d93 100644 --- a/g10/options.h +++ b/g10/options.h @@ -246,7 +246,7 @@ struct struct akl *next; } *auto_key_locate; - int passwd_repeat; + int passphrase_repeat; } opt; /* CTRL is used to keep some global variables we currently can't diff --git a/g10/passphrase.c b/g10/passphrase.c index eb1701b51..2133de569 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -644,7 +644,7 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo, /* Divert to the gpg-agent. */ pw = passphrase_get (keyid, mode == 2, s2k_cacheid, - (mode == 2 || mode == 4)? opt.passwd_repeat : 0, + (mode == 2 || mode == 4)? opt.passphrase_repeat : 0, tryagain_text, custdesc, custprompt, canceled); if (*canceled) {