Add an API to change passphrases. Currently only implemented for

GPGSM.  Requires GnuPG 2.1
This commit is contained in:
Werner Koch 2010-01-05 17:36:53 +00:00
parent 7eb555370f
commit 97c5d4d312
17 changed files with 312 additions and 29 deletions

26
NEWS
View File

@ -1,4 +1,4 @@
Noteworthy changes in version 1.2.1 (unreleased) Noteworthy changes in version 1.3.0 (unreleased)
------------------------------------------------ ------------------------------------------------
* GPGME does not come with an internal libassuan version anymore. * GPGME does not come with an internal libassuan version anymore.
@ -10,14 +10,21 @@ Noteworthy changes in version 1.2.1 (unreleased)
* New engine GPGME_PROTOCOL_UISERVER to support UI Servers. * New engine GPGME_PROTOCOL_UISERVER to support UI Servers.
* New API to change the passpgrase of a key.
* Interface changes relative to the 1.2.0 release: * Interface changes relative to the 1.2.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GPGME_STATUS_INV_SGNR NEW GPGME_STATUS_INV_SGNR NEW.
GPGME_STATUS_NO_SGNR NEW GPGME_STATUS_NO_SGNR NEW.
GPGME_PROTOCOL_G13 NEW GPGME_PROTOCOL_G13 NEW.
gpgme_op_g13_mount NEW gpgme_op_g13_mount NEW.
gpgme_g13_result_t NEW gpgme_g13_result_t NEW.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GPGME_PK_ECDSA NEW.
GPGME_PK_ECDH NEW.
gpgme_op_passwd_start NEW.
gpgme_op_passwd NEW.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 1.2.0 (2009-06-18) Noteworthy changes in version 1.2.0 (2009-06-18)
------------------------------------------------ ------------------------------------------------
@ -1321,7 +1328,8 @@ Noteworthy changes in version 0.2.1 (2001-04-02)
* Made the W32 support more robust. * Made the W32 support more robust.
Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008 g10 Code GmbH Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009,
2010 g10 Code GmbH
This file is free software; as a special exception the author gives This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without unlimited permission to copy and/or distribute it, with or without

2
README
View File

@ -1,7 +1,7 @@
GPGME - GnuPG Made Easy GPGME - GnuPG Made Easy
--------------------------- ---------------------------
Copyright 2004, 2006 g10 Code GmbH Copyright 2004, 2006, 2010 g10 Code GmbH
This file is free software; as a special exception the author gives This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without unlimited permission to copy and/or distribute it, with or without

View File

@ -1,6 +1,7 @@
# configure.ac for GPGME # configure.ac for GPGME
# Copyright (C) 2000 Werner Koch (dd9jn) # Copyright (C) 2000 Werner Koch (dd9jn)
# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 g10 Code GmbH # Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
# 2009, 2010 g10 Code GmbH
# #
# This file is part of GPGME. # This file is part of GPGME.
# #
@ -31,7 +32,7 @@ min_automake_version="1.10"
# specific feature can already be done under the assumption that the # specific feature can already be done under the assumption that the
# SVN version is the most recent one in a branch. To disable the SVN # SVN version is the most recent one in a branch. To disable the SVN
# version for the real release, set the my_issvn macro to no. # version for the real release, set the my_issvn macro to no.
m4_define(my_version, [1.2.1]) m4_define(my_version, [1.3.0])
m4_define(my_issvn, [yes]) m4_define(my_issvn, [yes])
m4_define([svn_revision], m4_esyscmd([printf "%d" $( (svn info 2>/dev/null \ m4_define([svn_revision], m4_esyscmd([printf "%d" $( (svn info 2>/dev/null \

View File

@ -1,3 +1,7 @@
2010-01-05 Werner Koch <wk@g10code.com>
* gpgme.texi (Changing Passphrases): New.
2009-07-21 Werner Koch <wk@g10code.com> 2009-07-21 Werner Koch <wk@g10code.com>
* uiserver.texi (UI Server Encrypt): Add --expect-sign option to * uiserver.texi (UI Server Encrypt): Add --expect-sign option to

View File

@ -13,7 +13,8 @@
@syncodeindex pg fn @syncodeindex pg fn
@copying @copying
Copyright @copyright{} 2002, 2003, 2004, 2005, 2006, 2007, 2008 g10 Code GmbH. Copyright @copyright{} 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2010 g10 Code GmbH.
@quotation @quotation
Permission is granted to copy, distribute and/or modify this document Permission is granted to copy, distribute and/or modify this document
@ -1014,6 +1015,18 @@ This value indicates ElGamal.
@item GPGME_PK_ELG_E @item GPGME_PK_ELG_E
This value also indicates ElGamal and is used specifically in GnuPG. This value also indicates ElGamal and is used specifically in GnuPG.
@item GPGME_PK_ELG_E
This value also indicates ElGamal and is used specifically in GnuPG.
@item GPGME_PK_ECDSA
This value indicates ECDSA, the Elliptic Curve Digital Signature
Algorithm as defined by FIPS 186-2.
@item GPGME_PK_ECDH
This value indicates ECDH, the Eliptic Curve Diffie-Hellmann encryption
algorithm as defined by the ECC in OpenPGP draft.
@end table @end table
@end deftp @end deftp
@ -2737,6 +2750,7 @@ in the list is the main (or primary) user ID.
* Exporting Keys:: Retrieving key data from the key ring. * Exporting Keys:: Retrieving key data from the key ring.
* Importing Keys:: Adding keys to the key ring. * Importing Keys:: Adding keys to the key ring.
* Deleting Keys:: Removing keys from the key ring. * Deleting Keys:: Removing keys from the key ring.
* Changing Passphrases:: Change the passphrase of a key.
* Advanced Key Editing:: Advanced key edit operation. * Advanced Key Editing:: Advanced key edit operation.
@end menu @end menu
@ -3715,6 +3729,38 @@ operation was started successfully, and @code{GPG_ERR_INV_VALUE} if
@end deftypefun @end deftypefun
@node Changing Passphrases
@subsection Changing Passphrases
@cindex passphrase, change
@deftypefun gpgme_error_t gpgme_op_passwd @
(@w{gpgme_ctx_t @var{ctx}}, @
@w{const gpgme_key_t @var{key}}, @
@w{unsigned int @var{flags}})
The function @code{gpgme_op_passwd} changes the passphrase of the
private key associated with @var{key}. The only allowed value for
@var{flags} is @code{0}. The backend engine will usually popup a window
to ask for the old and the new passphrase. Thus this function is not
useful in a server application (where passphrases are not required
anyway).
@end deftypefun
@deftypefun gpgme_error_t gpgme_op_passwd_start @
(@w{gpgme_ctx_t @var{ctx}}, @
@w{const gpgme_key_t @var{key}}, @
@w{unsigned int @var{flags}})
The function @code{gpgme_op_passwd_start} initiates a
@code{gpgme_op_passwd} operation. It can be completed by calling
@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
The function returns @code{0} if the operation was started successfully,
and an error code if one of the arguments is not valid or the oepration
could not be started.
@end deftypefun
@node Advanced Key Editing @node Advanced Key Editing
@subsection Advanced Key Editing @subsection Advanced Key Editing
@cindex key, edit @cindex key, edit

View File

@ -1,3 +1,21 @@
2010-01-05 Werner Koch <wk@g10code.com>
* gpgme-tool.c (gt_passwd, cmd_passwd): New.
(register_commands): Register.
* gpgme.h.in (gpgme_op_passwd_start, gpgme_op_passwd): New.
* libgpgme.vers, gpgme.def: Add new functions.
* passwd.c: New.
* Makefile.am (main_sources): Add passwd.c
* engine.c, engine.h (_gpgme_engine_op_passwd): New.
* engine-backend.h (struct engine_ops): Add PASSWD.
* engine-gpgsm.c (gpgsm_passwd): New.
(_gpgme_engine_ops_gpgsm): Register.
(gpgsm_reset): Reset only if we have a conenction.
* gpgme.h.in (GPGME_PK_ECDSA, GPGME_PK_ECDH): New.
* gpgme.c (gpgme_pubkey_algo_name): Add them.
2009-12-22 Marcus Brinkmann <marcus@g10code.de> 2009-12-22 Marcus Brinkmann <marcus@g10code.de>
* debug.c: Test for TLS, not __GNUC__ * debug.c: Test for TLS, not __GNUC__

View File

@ -115,7 +115,7 @@ main_sources = \
sign.c passphrase.c progress.c \ sign.c passphrase.c progress.c \
key.c keylist.c trust-item.c trustlist.c \ key.c keylist.c trust-item.c trustlist.c \
import.c export.c genkey.c delete.c edit.c getauditlog.c \ import.c export.c genkey.c delete.c edit.c getauditlog.c \
opassuan.c \ opassuan.c passwd.c \
engine.h engine-backend.h engine.c engine-gpg.c status-table.h \ engine.h engine-backend.h engine.c engine-gpg.c status-table.h \
$(gpgsm_components) $(assuan_components) $(gpgconf_components) \ $(gpgsm_components) $(assuan_components) $(gpgconf_components) \
$(uiserver_components) \ $(uiserver_components) \

View File

@ -118,6 +118,9 @@ struct engine_ops
/* Cancel only the current operation, not the whole session. */ /* Cancel only the current operation, not the whole session. */
gpgme_error_t (*cancel_op) (void *engine); gpgme_error_t (*cancel_op) (void *engine);
/* Change the passphrase for KEY. */
gpgme_error_t (*passwd) (void *engine, gpgme_key_t key, unsigned int flags);
}; };

View File

@ -1,6 +1,7 @@
/* engine-gpgsm.c - GpgSM engine. /* engine-gpgsm.c - GpgSM engine.
Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 g10 Code GmbH Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009,
2010 g10 Code GmbH
This file is part of GPGME. This file is part of GPGME.
@ -1053,13 +1054,18 @@ gpgsm_reset (void *engine)
{ {
engine_gpgsm_t gpgsm = engine; engine_gpgsm_t gpgsm = engine;
/* We must send a reset because we need to reset the list of /* IF we have an active connection we must send a reset because we
signers. Note that RESET does not reset OPTION commands. */ need to reset the list of signers. Note that RESET does not
return gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "RESET", NULL, NULL); reset OPTION commands. */
return (gpgsm->assuan_ctx
? gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "RESET",
NULL, NULL)
: 0);
} }
#endif #endif
static gpgme_error_t static gpgme_error_t
gpgsm_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain) gpgsm_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
{ {
@ -1894,6 +1900,32 @@ gpgsm_io_event (void *engine, gpgme_event_io_t type, void *type_data)
} }
static gpgme_error_t
gpgsm_passwd (void *engine, gpgme_key_t key, unsigned int flags)
{
engine_gpgsm_t gpgsm = engine;
gpgme_error_t err;
char *line;
if (!key || !key->subkeys || !key->subkeys->fpr)
return gpg_error (GPG_ERR_INV_VALUE);
if (asprintf (&line, "PASSWD -- %s", key->subkeys->fpr) < 0)
return gpg_error_from_syserror ();
gpgsm_clear_fd (gpgsm, OUTPUT_FD);
gpgsm_clear_fd (gpgsm, INPUT_FD);
gpgsm_clear_fd (gpgsm, MESSAGE_FD);
gpgsm->inline_data = NULL;
err = start (gpgsm, line);
free (line);
return err;
}
struct engine_ops _gpgme_engine_ops_gpgsm = struct engine_ops _gpgme_engine_ops_gpgsm =
{ {
/* Static functions. */ /* Static functions. */
@ -1937,5 +1969,6 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
gpgsm_set_io_cbs, gpgsm_set_io_cbs,
gpgsm_io_event, gpgsm_io_event,
gpgsm_cancel, gpgsm_cancel,
NULL /* cancel_op */ NULL, /* cancel_op */
gpgsm_passwd
}; };

View File

@ -1,6 +1,6 @@
/* engine.c - GPGME engine support. /* engine.c - GPGME engine support.
Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003, 2004, 2006, 2009 g10 Code GmbH Copyright (C) 2001, 2002, 2003, 2004, 2006, 2009, 2010 g10 Code GmbH
This file is part of GPGME. This file is part of GPGME.
@ -906,3 +906,19 @@ _gpgme_engine_cancel_op (engine_t engine)
return (*engine->ops->cancel_op) (engine->engine); return (*engine->ops->cancel_op) (engine->engine);
} }
/* Change the passphrase for KEY. */
gpgme_error_t
_gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
unsigned int flags)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->passwd)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->passwd) (engine->engine, key, flags);
}

View File

@ -1,6 +1,6 @@
/* engine.h - GPGME engine interface. /* engine.h - GPGME engine interface.
Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH Copyright (C) 2001, 2002, 2003, 2004, 2010 g10 Code GmbH
This file is part of GPGME. This file is part of GPGME.
@ -157,4 +157,8 @@ gpgme_error_t _gpgme_engine_cancel (engine_t engine);
gpgme_error_t _gpgme_engine_cancel_op (engine_t engine); gpgme_error_t _gpgme_engine_cancel_op (engine_t engine);
gpgme_error_t _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
unsigned int flags);
#endif /* ENGINE_H */ #endif /* ENGINE_H */

View File

@ -1,6 +1,5 @@
/* gpgme-tool.c - GnuPG Made Easy. /* gpgme-tool.c - GnuPG Made Easy.
Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2009, 2010 g10 Code GmbH
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH
This file is part of GPGME. This file is part of GPGME.
@ -15,9 +14,8 @@
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software License along with this program; if not, see <http://www.gnu.org/licenses/>.
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA */
02111-1307, USA. */
#if HAVE_CONFIG_H #if HAVE_CONFIG_H
#include <config.h> #include <config.h>
@ -1119,7 +1117,30 @@ gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags)
} }
// TODO static const char hlp_passwd[] =
"PASSWD <user-id>\n"
"\n"
"Ask the backend to change the passphrase for the key\n"
"specified by USER-ID.";
gpg_error_t
gt_passwd (gpgme_tool_t gt, char *fpr)
{
gpg_error_t err;
gpgme_key_t key;
err = gpgme_get_key (gt->ctx, fpr, &key, 0);
if (err)
return err;
err = gpgme_op_passwd (gt->ctx, key, 0);
gpgme_key_unref (key);
return err;
}
/* TODO */
#define GT_RESULT_ENCRYPT 0x1 #define GT_RESULT_ENCRYPT 0x1
#define GT_RESULT_DECRYPT 0x2 #define GT_RESULT_DECRYPT 0x2
#define GT_RESULT_SIGN 0x4 #define GT_RESULT_SIGN 0x4
@ -1974,6 +1995,16 @@ cmd_vfs_create (assuan_context_t ctx, char *line)
} }
static gpg_error_t
cmd_passwd (assuan_context_t ctx, char *line)
{
struct server *server = assuan_get_pointer (ctx);
return gt_passwd (server->gt, line);
}
static gpg_error_t static gpg_error_t
cmd_result (assuan_context_t ctx, char *line) cmd_result (assuan_context_t ctx, char *line)
{ {
@ -2076,6 +2107,7 @@ register_commands (assuan_context_t ctx)
{ "STRERROR", cmd_strerror }, { "STRERROR", cmd_strerror },
{ "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name }, { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
{ "HASH_ALGO_NAME", cmd_hash_algo_name }, { "HASH_ALGO_NAME", cmd_hash_algo_name },
{ "PASSWD", cmd_passwd, hlp_passwd },
{ NULL } { NULL }
}; };
int idx; int idx;

View File

@ -792,6 +792,12 @@ gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo)
case GPGME_PK_ELG: case GPGME_PK_ELG:
return "ELG"; return "ELG";
case GPGME_PK_ECDSA:
return "ECDSA";
case GPGME_PK_ECDH:
return "ECDH";
default: default:
return NULL; return NULL;
} }

View File

@ -196,5 +196,8 @@ EXPORTS
gpgme_set_sub_protocol @150 gpgme_set_sub_protocol @150
gpgme_get_sub_protocol @151 gpgme_get_sub_protocol @151
gpgme_op_passwd_start @152
gpgme_op_passwd @153
; END ; END

View File

@ -1,6 +1,7 @@
/* gpgme.h - Public interface to GnuPG Made Easy. -*- c -*- /* gpgme.h - Public interface to GnuPG Made Easy. -*- c -*-
Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 g10 Code GmbH Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009
2010 g10 Code GmbH
This file is part of GPGME. This file is part of GPGME.
@ -209,7 +210,9 @@ typedef enum
GPGME_PK_RSA_S = 3, GPGME_PK_RSA_S = 3,
GPGME_PK_ELG_E = 16, GPGME_PK_ELG_E = 16,
GPGME_PK_DSA = 17, GPGME_PK_DSA = 17,
GPGME_PK_ELG = 20 GPGME_PK_ELG = 20,
GPGME_PK_ECDSA = 301,
GPGME_PK_ECDH = 302
} }
gpgme_pubkey_algo_t; gpgme_pubkey_algo_t;
@ -1664,6 +1667,14 @@ gpgme_error_t gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key);
/* Terminate a pending keylist operation within CTX. */ /* Terminate a pending keylist operation within CTX. */
gpgme_error_t gpgme_op_keylist_end (gpgme_ctx_t ctx); gpgme_error_t gpgme_op_keylist_end (gpgme_ctx_t ctx);
/* Change the passphrase for KEY. FLAGS is reserved for future use
and must be passed as 0. */
gpgme_error_t gpgme_op_passwd_start (gpgme_ctx_t ctx, gpgme_key_t key,
unsigned int flags);
gpgme_error_t gpgme_op_passwd (gpgme_ctx_t ctx, gpgme_key_t key,
unsigned int flags);
/* Trust items and operations. */ /* Trust items and operations. */

View File

@ -76,6 +76,9 @@ GPGME_1.1 {
gpgme_key_from_uid; gpgme_key_from_uid;
gpgme_set_sub_protocol; gpgme_set_sub_protocol;
gpgme_get_sub_protocol; gpgme_get_sub_protocol;
gpgme_op_passwd_start;
gpgme_op_passwd;
}; };

95
src/passwd.c Normal file
View File

@ -0,0 +1,95 @@
/* passwd.c - Passphrase changing function
Copyright (C) 2010 g10 Code GmbH
This file is part of GPGME.
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include "gpgme.h"
#include "debug.h"
#include "context.h"
#include "ops.h"
static gpgme_error_t
passwd_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
(void)priv;
(void)code;
(void)args;
return 0;
}
static gpgme_error_t
passwd_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key,
unsigned int flags)
{
gpgme_error_t err;
if (!key)
return gpg_error (GPG_ERR_INV_VALUE);
if (flags)
return gpg_error (GPG_ERR_INV_FLAG);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
return err;
_gpgme_engine_set_status_handler (ctx->engine, passwd_status_handler, ctx);
return _gpgme_engine_op_passwd (ctx->engine, key, flags);
}
/* Change the passphrase for KEY. FLAGS is reserved for future use
and must be passed as 0. The engine is expected to present a user
interface to enter the old and the new passphrase. This is the
asynchronous variant.
Note that if ever the need arises to supply a passphrase we can do
this with a flag value and the passphrase callback feature. */
gpgme_error_t
gpgme_op_passwd_start (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags)
{
gpg_error_t err;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_passwd_start", ctx,
"key=%p, flags=0x%x", key, flags);
err = passwd_start (ctx, 0, key, flags);
return TRACE_ERR (err);
}
/* Change the passphrase for KEY. FLAGS is reserved for future use
and must be passed as 0. This is the synchronous variant. */
gpgme_error_t
gpgme_op_passwd (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags)
{
gpgme_error_t err;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_passwd", ctx,
"key=%p, flags=0x%x", key, flags);
err = passwd_start (ctx, 1, key, flags);
if (!err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);
}