diff options
| author | Werner Koch <[email protected]> | 2015-06-08 10:34:49 +0000 | 
|---|---|---|
| committer | Werner Koch <[email protected]> | 2015-06-08 10:34:49 +0000 | 
| commit | ddbd54ef881bd2c3481d62b89bef7241667b64ee (patch) | |
| tree | 0ca8940dceec227a335e4eb14fdaacc4be559fb6 /src | |
| parent | tests: Add option --secret to run-keylist. (diff) | |
| download | gpgme-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]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/engine-gpgsm.c | 46 | 
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); | 
