aboutsummaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
Diffstat (limited to 'agent')
-rw-r--r--agent/ChangeLog10
-rw-r--r--agent/call-pinentry.c52
-rw-r--r--agent/command.c64
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);
}
}