diff --git a/agent/ChangeLog b/agent/ChangeLog index 635259d44..25aa478e8 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,6 +1,9 @@ 2009-03-17 Werner Koch * command.c (cmd_get_passphrase): Break repeat loop on error. + Show error message. + (cmd_getinfo): Add subcommand "cmd_has_option". + (command_has_option): New. 2009-03-17 Daiki Ueno diff --git a/agent/command.c b/agent/command.c index 9451f27fe..1f8febc7b 100644 --- a/agent/command.c +++ b/agent/command.c @@ -105,6 +105,10 @@ struct } eventcounter; + +/* Local prototypes. */ +static int command_has_option (const char *cmd, const char *cmdopt); + @@ -1046,6 +1050,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line) char *p; void *cache_marker; int opt_data, opt_check, opt_no_ask, opt_repeat = 0; + char *repeat_errtext = NULL; opt_data = has_option (line, "--data"); opt_check = has_option (line, "--check"); @@ -1125,7 +1130,10 @@ cmd_get_passphrase (assuan_context_t ctx, char *line) plus_to_blank (desc); next_try: - rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext); + rc = agent_get_passphrase (ctrl, &response, desc, prompt, + repeat_errtext? repeat_errtext:errtext); + xfree (repeat_errtext); + repeat_errtext = NULL; if (!rc) { int i; @@ -1147,6 +1155,13 @@ cmd_get_passphrase (assuan_context_t ctx, char *line) { xfree (response2); xfree (response); + repeat_errtext = try_percent_escape + (_("does not match - try again"), NULL); + if (!repeat_errtext) + { + rc = gpg_error_from_syserror (); + break; + } goto next_try; } xfree (response2); @@ -1599,6 +1614,9 @@ cmd_reloadagent (assuan_context_t ctx, char *line) socket_name - Return the name of the socket. ssh_socket_name - Return the name of the ssh socket. scd_running - Return OK if the SCdaemon is already running. + + cmd_has_option CMD OPT + - Returns OK if the command CMD implements the option OPT. */ static int cmd_getinfo (assuan_context_t ctx, char *line) @@ -1639,6 +1657,38 @@ cmd_getinfo (assuan_context_t ctx, char *line) { rc = agent_scd_check_running ()? 0 : gpg_error (GPG_ERR_GENERAL); } + else if (!strncmp (line, "cmd_has_option", 14) + && (line[14] == ' ' || line[14] == '\t' || !line[14])) + { + char *cmd, *cmdopt; + line += 14; + while (*line == ' ' || *line == '\t') + line++; + if (!*line) + rc = gpg_error (GPG_ERR_MISSING_VALUE); + else + { + cmd = line; + while (*line && (*line != ' ' && *line != '\t')) + line++; + if (!*line) + rc = gpg_error (GPG_ERR_MISSING_VALUE); + else + { + *line++ = 0; + while (*line == ' ' || *line == '\t') + line++; + if (!*line) + rc = gpg_error (GPG_ERR_MISSING_VALUE); + else + { + cmdopt = line; + if (!command_has_option (cmd, cmdopt)) + rc = gpg_error (GPG_ERR_GENERAL); + } + } + } + } else rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT"); return rc; @@ -1765,6 +1815,20 @@ io_monitor (assuan_context_t ctx, int direction, } +/* Return true if the commznd CMD implements the option OPT. */ +static int +command_has_option (const char *cmd, const char *cmdopt) +{ + if (!strcmp (cmd, "GET_PASSPHRASE")) + { + if (!strcmp (cmdopt, "repeat")) + return 1; + } + + return 0; +} + + /* Tell the assuan library about our commands */ static int register_commands (assuan_context_t ctx) diff --git a/g10/ChangeLog b/g10/ChangeLog index 3bb5bf992..959655f35 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2009-03-17 Werner Koch + + * call-agent.c (my_percent_plus_escape): Remove. + (agent_get_passphrase): Rewrite using percent_plus_escape. + 2009-03-17 Daiki Ueno * passphrase.c (passphrase_get): Add extra arg REPEAT and adjust diff --git a/g10/call-agent.c b/g10/call-agent.c index fb66602f8..b6c61aa0e 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -144,29 +144,6 @@ unescape_status_string (const unsigned char *s) return buffer; } -/* Copy the text ATEXT into the buffer P and do plus '+' and percent - escaping. Note that the provided buffer needs to be 3 times the - size of ATEXT plus 1. Returns a pointer to the leading Nul in P. */ -static char * -my_percent_plus_escape (char *p, const char *atext) -{ - const unsigned char *s; - - for (s=atext; *s; s++) - { - if (*s < ' ' || *s == '+' || *s == '%') - { - snprintf (p, 4, "%%%02X", *s); - p += 3; - } - else if (*s == ' ') - *p++ = '+'; - else - *p++ = *s; - } - *p = 0; - return p; -} /* Take a 20 byte hexencoded string and put it into the the provided 20 byte buffer FPR in binary format. */ @@ -878,8 +855,11 @@ agent_get_passphrase (const char *cache_id, char **r_passphrase) { int rc; - char *line, *p; - char cmd[] = "GET_PASSPHRASE --data --repeat=%d -- "; + char line[ASSUAN_LINELENGTH]; + char *arg1 = NULL; + char *arg2 = NULL; + char *arg3 = NULL; + char *arg4 = NULL; membuf_t data; *r_passphrase = NULL; @@ -888,41 +868,37 @@ agent_get_passphrase (const char *cache_id, if (rc) return rc; - /* We allocate 3 times the needed space for the texts so that - there is enough space for escaping. */ - line = xtrymalloc ( strlen (cmd) + sizeof(repeat) + 1 - + (cache_id? 3*strlen (cache_id): 1) + 1 - + (err_msg? 3*strlen (err_msg): 1) + 1 - + (prompt? 3*strlen (prompt): 1) + 1 - + (desc_msg? 3*strlen (desc_msg): 1) + 1 - + 1); - if (!line) - return gpg_error_from_syserror (); + /* Check that the gpg-agent understands the repeat option. */ + if (assuan_transact (agent_ctx, + "GETINFO cmd_has_option GET_PASSPHRASE repeat", + NULL, NULL, NULL, NULL, NULL, NULL)) + return gpg_error (GPG_ERR_NOT_SUPPORTED); - p = line + sprintf (line, cmd, repeat); if (cache_id && *cache_id) - p = my_percent_plus_escape (p, cache_id); - else - *p++ = 'X'; - *p++ = ' '; - + if (!(arg1 = percent_plus_escape (cache_id))) + goto no_mem; if (err_msg && *err_msg) - p = my_percent_plus_escape (p, err_msg); - else - *p++ = 'X'; - *p++ = ' '; - + if (!(arg2 = percent_plus_escape (err_msg))) + goto no_mem; if (prompt && *prompt) - p = my_percent_plus_escape (p, prompt); - else - *p++ = 'X'; - *p++ = ' '; - + if (!(arg3 = percent_plus_escape (prompt))) + goto no_mem; if (desc_msg && *desc_msg) - p = my_percent_plus_escape (p, desc_msg); - else - *p++ = 'X'; - *p = 0; + if (!(arg4 = percent_plus_escape (desc_msg))) + goto no_mem; + + snprintf (line, DIM(line)-1, + "GET_PASSPHRASE --data --repeat=%d -- %s %s %s %s", + repeat, + arg1? arg1:"X", + arg2? arg2:"X", + arg3? arg3:"X", + arg4? arg4:"X"); + line[DIM(line)-1] = 0; + xfree (arg1); + xfree (arg2); + xfree (arg3); + xfree (arg4); init_membuf_secure (&data, 64); rc = assuan_transact (agent_ctx, line, @@ -938,7 +914,13 @@ agent_get_passphrase (const char *cache_id, if (!*r_passphrase) rc = gpg_error_from_syserror (); } - xfree (line); + return rc; + no_mem: + rc = gpg_error_from_syserror (); + xfree (arg1); + xfree (arg2); + xfree (arg3); + xfree (arg4); return rc; }