diff options
Diffstat (limited to 'agent')
-rw-r--r-- | agent/ChangeLog | 10 | ||||
-rw-r--r-- | agent/call-pinentry.c | 52 | ||||
-rw-r--r-- | agent/command.c | 64 |
3 files changed, 90 insertions, 36 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog index b9020772d..fc0308255 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,13 @@ +2006-10-04 Werner Koch <[email protected]> + + * call-pinentry.c (agent_get_passphrase): Changed to return the + unencoded passphrase. + (agent_askpin, agent_get_passphrase, agent_get_confirmation): Need + to map the cancel error. + * command.c (send_back_passphrase): New. + (cmd_get_passphrase): Use it here. Also implement --data option. + (skip_options): New. + 2006-09-26 Werner Koch <[email protected]> * learncard.c (agent_handle_learn): Send back the keypair diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c index 734cf45b9..e6b4c6a60 100644 --- a/agent/call-pinentry.c +++ b/agent/call-pinentry.c @@ -413,6 +413,13 @@ agent_askpin (ctrl_t ctrl, rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL); + /* Most pinentries out in the wild return the old Assuan error code + for canceled which gets translated to an assuan Cancel error and + not to the code for a user cancel. Fix this here. */ + if (rc && gpg_err_source (rc) + && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED) + rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED); + if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA) errtext = is_pin? _("PIN too long") : _("Passphrase too long"); @@ -456,9 +463,8 @@ agent_askpin (ctrl_t ctrl, -/* Ask for the passphrase using the supplied arguments. The - passphrase is returned in RETPASS as an hex encoded string to be - freed by the caller */ +/* Ask for the passphrase using the supplied arguments. The returned + passphrase needs to be freed by the caller. */ int agent_get_passphrase (ctrl_t ctrl, char **retpass, const char *desc, const char *prompt, @@ -468,9 +474,6 @@ agent_get_passphrase (ctrl_t ctrl, int rc; char line[ASSUAN_LINELENGTH]; struct entry_parm_s parm; - unsigned char *p; - char *hexstring; - int i; *retpass = NULL; if (opt.batch) @@ -515,27 +518,18 @@ agent_get_passphrase (ctrl_t ctrl, return unlock_pinentry (out_of_core ()); assuan_begin_confidential (entry_ctx); - rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL); + rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, + NULL, NULL, NULL, NULL); + /* Most pinentries out in the wild return the old Assuan error code + for canceled which gets translated to an assuan Cancel error and + not to the code for a user cancel. Fix this here. */ + if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED) + rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED); if (rc) - { - xfree (parm.buffer); - return unlock_pinentry (rc); - } - - hexstring = gcry_malloc_secure (strlen ((char*)parm.buffer)*2+1); - if (!hexstring) - { - gpg_error_t tmperr = out_of_core (); - xfree (parm.buffer); - return unlock_pinentry (tmperr); - } - - for (i=0, p=parm.buffer; *p; p++, i += 2) - sprintf (hexstring+i, "%02X", *p); - - xfree (parm.buffer); - *retpass = hexstring; - return unlock_pinentry (0); + xfree (parm.buffer); + else + *retpass = parm.buffer; + return unlock_pinentry (rc); } @@ -561,6 +555,12 @@ agent_get_confirmation (ctrl_t ctrl, snprintf (line, DIM(line)-1, "RESET"); line[DIM(line)-1] = 0; rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + /* Most pinentries out in the wild return the old Assuan error code + for canceled which gets translated to an assuan Cancel error and + not to the code for a user cancel. Fix this here. */ + if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED) + rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED); + if (rc) return unlock_pinentry (rc); diff --git a/agent/command.c b/agent/command.c index a77ceaff2..900bfee01 100644 --- a/agent/command.c +++ b/agent/command.c @@ -136,6 +136,23 @@ has_option (const char *line, const char *name) return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); } +/* Skip over options. It is assumed that leading spaces have been + removed (this is the case for lines passed to a handler from + assuan). Bkanls after the options are also removed. */ +static char * +skip_options (char *line) +{ + while ( *line == '-' && line[1] == '-' ) + { + while (*line && !spacep (line)) + line++; + while (spacep (line)) + line++; + } + return line; +} + + /* Replace all '+' by a blank. */ static void plus_to_blank (char *s) @@ -639,7 +656,33 @@ cmd_readkey (assuan_context_t ctx, char *line) -/* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>] +static int +send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw) +{ + size_t n; + int rc; + + assuan_begin_confidential (ctx); + n = strlen (pw); + if (via_data) + rc = assuan_send_data (ctx, pw, n); + else + { + char *p = xtrymalloc_secure (n*2+1); + if (!p) + rc = gpg_error_from_syserror (); + else + { + bin2hex (pw, n, p); + rc = assuan_set_okay_line (ctx, p); + xfree (p); + } + } + return rc; +} + + +/* GET_PASSPHRASE [--data] <cache_id> [<error_message> <prompt> <description>] This function is usually used to ask for a passphrase to be used for conventional encryption, but may also be used by programs which @@ -648,6 +691,9 @@ cmd_readkey (assuan_context_t ctx, char *line) agent either returns with an error or with a OK followed by the hex encoded passphrase. Note that the length of the strings is implicitly limited by the maximum length of a command. + + If the option "--data" is used the passphrase is returned by usual + data lines and not on the okay line. */ static int @@ -660,11 +706,12 @@ cmd_get_passphrase (assuan_context_t ctx, char *line) char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL; char *p; void *cache_marker; + int opt_data; - /* parse the stuff */ - for (p=line; *p == ' '; p++) - ; - cacheid = p; + opt_data = has_option (line, "--data"); + line = skip_options (line); + + cacheid = line; p = strchr (cacheid, ' '); if (p) { @@ -706,13 +753,11 @@ cmd_get_passphrase (assuan_context_t ctx, char *line) if (!strcmp (desc, "X")) desc = NULL; - /* Note: we store the hexified versions in the cache. */ pw = cacheid ? agent_get_cache (cacheid, CACHE_MODE_NORMAL, &cache_marker) : NULL; if (pw) { - assuan_begin_confidential (ctx); - rc = assuan_set_okay_line (ctx, pw); + rc = send_back_passphrase (ctx, opt_data, pw); agent_unlock_cache_entry (&cache_marker); } else @@ -733,8 +778,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line) { if (cacheid) agent_put_cache (cacheid, CACHE_MODE_USER, response, 0); - assuan_begin_confidential (ctx); - rc = assuan_set_okay_line (ctx, response); + rc = send_back_passphrase (ctx, opt_data, response); xfree (response); } } |