1 /* passwd.c - Passphrase changing function
2 Copyright (C) 2010 g10 Code GmbH
4 This file is part of GPGME.
6 GPGME is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of
9 the License, or (at your option) any later version.
11 GPGME is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this program; if not, see <https://www.gnu.org/licenses/>.
33 /* The error code from a FAILURE status line or 0. */
34 gpg_error_t failure_code;
42 /* Parse an error status line and return the error code. */
44 parse_error (char *args)
47 char *where = strchr (args, ' ');
55 where = strchr (which, ' ');
62 return trace_gpg_error (GPG_ERR_INV_ENGINE);
66 if (!strcmp (where, "keyedit.passwd"))
74 passwd_status_handler (void *priv, gpgme_status_code_t code, char *args)
76 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
81 err = _gpgme_op_data_lookup (ctx, OPDATA_PASSWD, &hook, -1, NULL);
88 case GPGME_STATUS_ERROR:
89 err = parse_error (args);
94 case GPGME_STATUS_SUCCESS:
95 opd->success_seen = 1;
98 case GPGME_STATUS_FAILURE:
99 opd->failure_code = _gpgme_parse_failure (args);
102 case GPGME_STATUS_EOF:
103 /* In case the OpenPGP engine does not properly implement the
104 passwd command we won't get a success status back and thus we
105 conclude that this operation is not supported. This is for
106 example the case for GnuPG < 2.0.16. Note that this test is
107 obsolete for assuan based engines because they will properly
108 return an error for an unknown command. */
109 if (ctx->protocol == GPGME_PROTOCOL_OpenPGP
110 && !opd->error_seen && !opd->success_seen)
111 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
112 else if (opd->failure_code)
113 err = opd->failure_code;
125 passwd_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key,
133 return gpg_error (GPG_ERR_INV_VALUE);
135 return gpg_error (GPG_ERR_INV_FLAG);
137 err = _gpgme_op_reset (ctx, synchronous);
141 err = _gpgme_op_data_lookup (ctx, OPDATA_PASSWD, &hook, sizeof (*opd), NULL);
146 opd->success_seen = 0;
149 _gpgme_engine_set_status_handler (ctx->engine, passwd_status_handler, ctx);
151 if (ctx->passphrase_cb)
153 err = _gpgme_engine_set_command_handler
154 (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
159 return _gpgme_engine_op_passwd (ctx->engine, key, flags);
164 /* Change the passphrase for KEY. FLAGS is reserved for future use
165 and must be passed as 0. The engine is expected to present a user
166 interface to enter the old and the new passphrase. This is the
167 asynchronous variant.
169 Note that if ever the need arises to supply a passphrase we can do
170 this with a flag value and the passphrase callback feature. */
172 gpgme_op_passwd_start (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags)
175 TRACE_BEG2 (DEBUG_CTX, "gpgme_op_passwd_start", ctx,
176 "key=%p, flags=0x%x", key, flags);
179 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
181 err = passwd_start (ctx, 0, key, flags);
182 return TRACE_ERR (err);
186 /* Change the passphrase for KEY. FLAGS is reserved for future use
187 and must be passed as 0. This is the synchronous variant. */
189 gpgme_op_passwd (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags)
193 TRACE_BEG2 (DEBUG_CTX, "gpgme_op_passwd", ctx,
194 "key=%p, flags=0x%x", key, flags);
197 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
199 err = passwd_start (ctx, 1, key, flags);
201 err = _gpgme_wait_one (ctx);
202 return TRACE_ERR (err);