diff --git a/NEWS b/NEWS index f85d50ef..072ddeea 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ Noteworthy changes in version 1.3.1 (unreleased) * Under development. + * Detect GPG versions not supporting ---passwd. + * Interface changes relative to the 1.3.0 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GPGME_EXPORT_MODE_MINIMAL NEW. diff --git a/src/ChangeLog b/src/ChangeLog index 2582893e..887fbc5a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2010-03-12 Werner Koch + + * passwd.c (op_data_t): New. + (passwd_start): Setup OPD. + (passwd_status_handler): Return GPG_ERR_NOT_SUPPORTED if needed. + * context.h (OPDATA_PASSWD): New. + * gpgme.h (GPGME_STATUS_SUCCESS): New. + 2010-03-09 Werner Koch * engine-gpgsm.c (gpgsm_keylist): Try to start the agent. diff --git a/src/context.h b/src/context.h index 19c7194b..69d8d9bd 100644 --- a/src/context.h +++ b/src/context.h @@ -37,7 +37,8 @@ typedef enum { OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE, OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT, - OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT + OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT, + OPDATA_PASSWD } ctx_op_data_id_t; diff --git a/src/passwd.c b/src/passwd.c index 67668770..ab61b4a4 100644 --- a/src/passwd.c +++ b/src/passwd.c @@ -27,6 +27,14 @@ #include "context.h" #include "ops.h" + +typedef struct +{ + int success_seen; + int error_seen; +} *op_data_t; + + /* Parse an error status line and return the error code. */ static gpgme_error_t @@ -63,16 +71,39 @@ static gpgme_error_t passwd_status_handler (void *priv, gpgme_status_code_t code, char *args) { gpgme_ctx_t ctx = (gpgme_ctx_t) priv; - gpgme_error_t err = 0; + gpgme_error_t err; + void *hook; + op_data_t opd; - (void)ctx; + err = _gpgme_op_data_lookup (ctx, OPDATA_PASSWD, &hook, -1, NULL); + opd = hook; + if (err) + return err; switch (code) { case GPGME_STATUS_ERROR: err = parse_error (args); + if (err) + opd->error_seen = 1; break; - + + case GPGME_STATUS_SUCCESS: + opd->success_seen = 1; + break; + + case GPGME_STATUS_EOF: + /* In case the OpenPGP engine does not properly implement the + passwd command we won't get a success status back and thus we + conclude that this operation is not supported. This is for + example the case for GnuPG < 2.0.16. Note that this test is + obsolete for assuan based engines because they will properly + return an error for an unknown command. */ + if (ctx->protocol == GPGME_PROTOCOL_OpenPGP + && !opd->error_seen && !opd->success_seen) + err = gpg_error (GPG_ERR_NOT_SUPPORTED); + break; + default: break; } @@ -86,6 +117,8 @@ passwd_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key, unsigned int flags) { gpgme_error_t err; + void *hook; + op_data_t opd; if (!key) return gpg_error (GPG_ERR_INV_VALUE); @@ -96,6 +129,14 @@ passwd_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key, if (err) return err; + err = _gpgme_op_data_lookup (ctx, OPDATA_PASSWD, &hook, sizeof (*opd), NULL); + opd = hook; + if (err) + return err; + + opd->success_seen = 0; + opd->error_seen = 0; + _gpgme_engine_set_status_handler (ctx->engine, passwd_status_handler, ctx); return _gpgme_engine_op_passwd (ctx->engine, key, flags);