aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2015-06-08 10:34:49 +0000
committerWerner Koch <[email protected]>2015-06-08 10:34:49 +0000
commitddbd54ef881bd2c3481d62b89bef7241667b64ee (patch)
tree0ca8940dceec227a335e4eb14fdaacc4be559fb6
parenttests: Add option --secret to run-keylist. (diff)
downloadgpgme-ddbd54ef881bd2c3481d62b89bef7241667b64ee.tar.gz
gpgme-ddbd54ef881bd2c3481d62b89bef7241667b64ee.zip
Fix regression with gpgsm 2.0 due to "OPTION with-secret".
* src/engine-gpgsm.c (gpgsm_assuan_simple_command): Do not terminate on a status lines. -- This bug has been with us since the support for gpgsm: If there is no status line handler but a status line is received anyway the command handling loop terminates and thus the command/answer order gets out of sync. In the case of the bug report this is triggered by sending an option which starts the agent and that starting emits a "PROGRESS" status line. The solution is not to stop reading after a status line but record a possible error code and return that only after OK or ERR. GnuPG-bug-id: 1795 Signed-off-by: Werner Koch <[email protected]>
-rw-r--r--src/engine-gpgsm.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c
index 3a837577..ac6c5fc6 100644
--- a/src/engine-gpgsm.c
+++ b/src/engine-gpgsm.c
@@ -564,7 +564,7 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
engine_status_handler_t status_fnc,
void *status_fnc_value)
{
- gpg_error_t err;
+ gpg_error_t err, cb_err;
char *line;
size_t linelen;
@@ -572,6 +572,7 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
if (err)
return err;
+ cb_err = 0;
do
{
err = assuan_read_line (ctx, &line, &linelen);
@@ -584,32 +585,45 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
if (linelen >= 2
&& line[0] == 'O' && line[1] == 'K'
&& (line[2] == '\0' || line[2] == ' '))
- return 0;
+ return cb_err;
else if (linelen >= 4
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
&& line[3] == ' ')
- err = atoi (&line[4]);
+ {
+ /* We prefer a callback generated error because that one is
+ more related to gpgme and thus probably more important
+ than the error returned by the engine. */
+ err = cb_err? cb_err : atoi (&line[4]);
+ }
else if (linelen >= 2
&& line[0] == 'S' && line[1] == ' ')
{
- char *rest;
- gpgme_status_code_t r;
+ /* After an error from a status callback we skip all further
+ status lines. */
+ if (!cb_err)
+ {
+ char *rest;
+ gpgme_status_code_t r;
- rest = strchr (line + 2, ' ');
- if (!rest)
- rest = line + linelen; /* set to an empty string */
- else
- *(rest++) = 0;
+ rest = strchr (line + 2, ' ');
+ if (!rest)
+ rest = line + linelen; /* set to an empty string */
+ else
+ *(rest++) = 0;
- r = _gpgme_parse_status (line + 2);
+ r = _gpgme_parse_status (line + 2);
- if (r >= 0 && status_fnc)
- err = status_fnc (status_fnc_value, r, rest);
- else
- err = gpg_error (GPG_ERR_GENERAL);
+ if (r >= 0 && status_fnc)
+ cb_err = status_fnc (status_fnc_value, r, rest);
+ }
}
else
- err = gpg_error (GPG_ERR_GENERAL);
+ {
+ /* Invalid line or INQUIRY. We can't do anything else than
+ to stop. As with ERR we prefer a status callback
+ generated error code, though. */
+ err = cb_err ? cb_err : gpg_error (GPG_ERR_GENERAL);
+ }
}
while (!err);