summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--agent/ChangeLog18
-rw-r--r--agent/Makefile.am6
-rw-r--r--agent/call-pinentry.c1
-rw-r--r--agent/call-scd.c40
-rw-r--r--agent/command.c38
-rw-r--r--agent/protect-tool.c274
-rw-r--r--common/ChangeLog19
-rw-r--r--common/Makefile.am5
-rw-r--r--common/exechelp.c11
-rw-r--r--common/get-passphrase.c277
-rw-r--r--common/get-passphrase.h47
-rw-r--r--common/membuf.c14
-rw-r--r--common/percent.c155
-rw-r--r--common/sysutils.c8
-rw-r--r--common/t-percent.c20
-rw-r--r--common/util.h5
-rw-r--r--g10/ChangeLog8
-rw-r--r--g10/call-agent.c27
-rw-r--r--g10/main.h1
-rw-r--r--g10/misc.c33
-rw-r--r--g10/passphrase.c5
-rw-r--r--scd/ChangeLog5
-rw-r--r--scd/command.c37
-rw-r--r--sm/ChangeLog6
-rw-r--r--sm/export.c12
-rw-r--r--sm/import.c12
-rw-r--r--tools/gpg-connect-agent.c2
-rw-r--r--tools/gpgconf-comp.c2
29 files changed, 719 insertions, 372 deletions
diff --git a/NEWS b/NEWS
index 015ca1663..f0667eb5e 100644
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,9 @@ Noteworthy changes in version 2.0.12 (not released)
* Support for the Telesec Netkey 3 cards.
+ * The gpg-protect-tool now uses gpg-agent via libassuan. Under
+ Windows the Pinentry will now be put into the foreground.
+
Noteworthy changes in version 2.0.11 (2009-03-03)
-------------------------------------------------
diff --git a/agent/ChangeLog b/agent/ChangeLog
index 10390da3f..e691ad7e6 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,3 +1,21 @@
+2009-04-01 Werner Koch <wk@g10code.com>
+
+ * protect-tool.c (pe_opt): New.
+ (opts): Add option --agent-program. Use ARGPARSE macros.
+ (get_new_passphrase): Remove.
+ (get_passphrase): Use gpg-agent directly. Remove arg OPT_CHECK and
+ change all callers.
+ * Makefile.am (gpg_protect_tool_LDADD): Replace pwquery_libs by
+ LIBASSUAN_LIBS.
+ (gpg_protect_tool_CFLAGS): New.
+
+ * command.c (percent_plus_unescape): Remove.
+ (cmd_putval): Use percent_plus_unescape_inplace.
+ * call-scd.c (unescape_status_string): Remove.
+ (card_getattr_cb): Use percent_plus_unescape.
+ * protect-tool.c (main): Use percent_plus_unescape from common/.
+ (percent_plus_unescape, percent_plus_unescape_string): Remove.
+
2009-03-27 Werner Koch <wk@g10code.com>
* learncard.c (agent_handle_learn): Add new certtype 111.
diff --git a/agent/Makefile.am b/agent/Makefile.am
index 95ffafeec..c2830a94b 100644
--- a/agent/Makefile.am
+++ b/agent/Makefile.am
@@ -74,9 +74,9 @@ gpg_protect_tool_SOURCES = \
protect.c \
minip12.c minip12.h
-# Needs $(NETLIBS) for libsimple-pwquery.la.
-gpg_protect_tool_LDADD = $(pwquery_libs) $(common_libs) \
- $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(NETLIBS) $(LIBICONV)
+gpg_protect_tool_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS)
+gpg_protect_tool_LDADD = $(common_libs) $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) \
+ $(GPG_ERROR_LIBS) $(LIBINTL) $(NETLIBS) $(LIBICONV)
gpg_preset_passphrase_SOURCES = \
preset-passphrase.c
diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index 86792d8d7..c840bb68d 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -105,6 +105,7 @@ static void
dump_mutex_state (pth_mutex_t *m)
{
#ifdef _W32_PTH_H
+ (void)m;
log_printf ("unknown under W32");
#else
if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
diff --git a/agent/call-scd.c b/agent/call-scd.c
index f45e94097..d09812e57 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -136,6 +136,7 @@ static void
dump_mutex_state (pth_mutex_t *m)
{
#ifdef _W32_PTH_H
+ (void)m;
log_printf ("unknown under W32");
#else
if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
@@ -562,43 +563,6 @@ agent_reset_scd (ctrl_t ctrl)
-/* Return a new malloced string by unescaping the string S. Escaping
- is percent escaping and '+'/space mapping. A binary Nul will
- silently be replaced by a 0xFF. Function returns NULL to indicate
- an out of memory status. */
-static char *
-unescape_status_string (const unsigned char *s)
-{
- char *buffer, *d;
-
- buffer = d = xtrymalloc (strlen ((const char*)s)+1);
- if (!buffer)
- return NULL;
- while (*s)
- {
- if (*s == '%' && s[1] && s[2])
- {
- s++;
- *d = xtoi_2 (s);
- if (!*d)
- *d = '\xff';
- d++;
- s += 2;
- }
- else if (*s == '+')
- {
- *d++ = ' ';
- s++;
- }
- else
- *d++ = *s++;
- }
- *d = 0;
- return buffer;
-}
-
-
-
static int
learn_status_cb (void *opaque, const char *line)
{
@@ -1045,7 +1009,7 @@ card_getattr_cb (void *opaque, const char *line)
if (keywordlen == parm->keywordlen
&& !memcmp (keyword, parm->keyword, keywordlen))
{
- parm->data = unescape_status_string ((const unsigned char*)line);
+ parm->data = percent_plus_unescape ((const unsigned char*)line, 0xff);
if (!parm->data)
parm->error = errno;
}
diff --git a/agent/command.c b/agent/command.c
index 56d390bd8..728b160a8 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -236,42 +236,6 @@ plus_to_blank (char *s)
}
-/* Do the percent and plus/space unescaping in place and return the
- length of the valid buffer. */
-static size_t
-percent_plus_unescape (char *string)
-{
- unsigned char *p = (unsigned char *)string;
- size_t n = 0;
-
- while (*string)
- {
- if (*string == '%' && string[1] && string[2])
- {
- string++;
- *p++ = xtoi_2 (string);
- n++;
- string+= 2;
- }
- else if (*string == '+')
- {
- *p++ = ' ';
- n++;
- string++;
- }
- else
- {
- *p++ = *string++;
- n++;
- }
- }
-
- return n;
-}
-
-
-
-
/* Parse a hex string. Return an Assuan error code or 0 on success and the
length of the parsed string in LEN. */
static int
@@ -1494,7 +1458,7 @@ cmd_putval (assuan_context_t ctx, char *line)
p = strchr (value, ' ');
if (p)
*p = 0;
- valuelen = percent_plus_unescape (value);
+ valuelen = percent_plus_unescape_inplace (value, 0);
}
}
if (!key || !*key)
diff --git a/agent/protect-tool.c b/agent/protect-tool.c
index 848ad9f4b..d0b68a1fa 100644
--- a/agent/protect-tool.c
+++ b/agent/protect-tool.c
@@ -41,13 +41,14 @@
#define JNLIB_NEED_LOG_LOGV
#include "agent.h"
#include "minip12.h"
-#include "simple-pwquery.h"
#include "i18n.h"
+#include "get-passphrase.h"
#include "sysutils.h"
enum cmd_and_opt_values
-{ aNull = 0,
+{
+ aNull = 0,
oVerbose = 'v',
oArmor = 'a',
oPassphrase = 'P',
@@ -72,17 +73,19 @@ enum cmd_and_opt_values
oPrompt,
oStatusMsg,
-aTest };
+ oAgentProgram
+};
+
struct rsa_secret_key_s
- {
- gcry_mpi_t n; /* public modulus */
- gcry_mpi_t e; /* public exponent */
- gcry_mpi_t d; /* exponent */
- gcry_mpi_t p; /* prime p. */
- gcry_mpi_t q; /* prime q. */
- gcry_mpi_t u; /* inverse of p mod q. */
- };
+{
+ gcry_mpi_t n; /* public modulus */
+ gcry_mpi_t e; /* public exponent */
+ gcry_mpi_t d; /* exponent */
+ gcry_mpi_t p; /* prime p. */
+ gcry_mpi_t q; /* prime q. */
+ gcry_mpi_t u; /* inverse of p mod q. */
+};
static const char *opt_homedir;
@@ -96,41 +99,51 @@ static const char *opt_passphrase;
static char *opt_prompt;
static int opt_status_msg;
static const char *opt_p12_charset;
+static const char *opt_agent_program;
-static char *get_passphrase (int promptno, int opt_check);
-static char *get_new_passphrase (int promptno);
+static char *get_passphrase (int promptno);
static void release_passphrase (char *pw);
static int store_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force);
static ARGPARSE_OPTS opts[] = {
+ ARGPARSE_group (300, N_("@Commands:\n ")),
+
+ ARGPARSE_c (oProtect, "protect", "protect a private key"),
+ ARGPARSE_c (oUnprotect, "unprotect", "unprotect a private key"),
+ ARGPARSE_c (oShadow, "shadow", "create a shadow entry for a public key"),
+ ARGPARSE_c (oShowShadowInfo, "show-shadow-info", "return the shadow info"),
+ ARGPARSE_c (oShowKeygrip, "show-keygrip", "show the \"keygrip\""),
+ ARGPARSE_c (oP12Import, "p12-import",
+ "import a pkcs#12 encoded private key"),
+ ARGPARSE_c (oP12Export, "p12-export",
+ "export a private key pkcs#12 encoded"),
- { 301, NULL, 0, N_("@Options:\n ") },
-
- { oVerbose, "verbose", 0, "verbose" },
- { oArmor, "armor", 0, "write output in advanced format" },
- { oCanonical, "canonical", 0, "write output in canonical format" },
- { oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" },
- { oProtect, "protect", 256, "protect a private key"},
- { oUnprotect, "unprotect", 256, "unprotect a private key"},
- { oShadow, "shadow", 256, "create a shadow entry for a public key"},
- { oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"},
- { oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""},
-
- { oP12Import, "p12-import", 256, "import a pkcs#12 encoded private key"},
- { oP12Export, "p12-export", 256, "export a private key pkcs#12 encoded"},
- { oP12Charset,"p12-charset", 2,
- "|NAME|set charset for a new PKCS#12 passphrase to NAME" },
- { oHaveCert, "have-cert", 0, "certificate to export provided on STDIN"},
- { oStore, "store", 0, "store the created key in the appropriate place"},
- { oForce, "force", 0, "force overwriting"},
- { oNoFailOnExist, "no-fail-on-exist", 0, "@" },
- { oHomedir, "homedir", 2, "@" },
- { oPrompt, "prompt", 2, "|ESCSTRING|use ESCSTRING as prompt in pinentry"},
- { oStatusMsg, "enable-status-msg", 0, "@"},
-
- {0}
+ ARGPARSE_group (301, N_("@\nOptions:\n ")),
+
+ ARGPARSE_s_n (oVerbose, "verbose", "verbose"),
+ ARGPARSE_s_n (oArmor, "armor", "write output in advanced format"),
+ ARGPARSE_s_n (oCanonical, "canonical", "write output in canonical format"),
+
+ ARGPARSE_s_s (oPassphrase, "passphrase", "|STRING|use passphrase STRING"),
+ ARGPARSE_s_s (oP12Charset,"p12-charset",
+ "|NAME|set charset for a new PKCS#12 passphrase to NAME"),
+ ARGPARSE_s_n (oHaveCert, "have-cert",
+ "certificate to export provided on STDIN"),
+ ARGPARSE_s_n (oStore, "store",
+ "store the created key in the appropriate place"),
+ ARGPARSE_s_n (oForce, "force",
+ "force overwriting"),
+ ARGPARSE_s_n (oNoFailOnExist, "no-fail-on-exist", "@"),
+ ARGPARSE_s_s (oHomedir, "homedir", "@"),
+ ARGPARSE_s_s (oPrompt, "prompt",
+ "|ESCSTRING|use ESCSTRING as prompt in pinentry"),
+ ARGPARSE_s_n (oStatusMsg, "enable-status-msg", "@"),
+
+ ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
+
+ ARGPARSE_end ()
};
static const char *
@@ -158,9 +171,6 @@ my_strusage (int level)
}
-/* Include the implementation of map_spwq_error. */
-MAP_SPWQ_ERROR_IMPL
-
/* static void */
/* print_mpi (const char *text, gcry_mpi_t a) */
/* { */
@@ -333,7 +343,7 @@ read_and_protect (const char *fname)
if (!key)
return;
- pw = get_passphrase (1, 0);
+ pw = get_passphrase (1);
rc = agent_protect (key, pw, &result, &resultlen);
release_passphrase (pw);
xfree (key);
@@ -372,7 +382,7 @@ read_and_unprotect (const char *fname)
if (!key)
return;
- rc = agent_unprotect (key, (pw=get_passphrase (1, 0)),
+ rc = agent_unprotect (key, (pw=get_passphrase (1)),
protected_at, &result, &resultlen);
release_passphrase (pw);
xfree (key);
@@ -678,7 +688,7 @@ import_p12_file (const char *fname)
buf_off = 0;
kparms = p12_parse ((unsigned char*)buf+buf_off, buflen-buf_off,
- (pw=get_passphrase (2, 0)),
+ (pw=get_passphrase (2)),
import_p12_cert_cb, NULL);
release_passphrase (pw);
xfree (buf);
@@ -753,12 +763,8 @@ import_p12_file (const char *fname)
assert (buflen);
gcry_sexp_release (s_key);
-
- pw = get_new_passphrase (4);
- if (!pw)
- rc = gpg_error (GPG_ERR_CANCELED);
- else
- rc = agent_protect (key, pw, &result, &resultlen);
+ pw = get_passphrase (4);
+ rc = agent_protect (key, pw, &result, &resultlen);
release_passphrase (pw);
xfree (key);
if (rc)
@@ -896,7 +902,7 @@ export_p12_file (const char *fname)
unsigned char *tmpkey;
size_t tmplen;
- rc = agent_unprotect (key, (pw=get_passphrase (1, 0)),
+ rc = agent_unprotect (key, (pw=get_passphrase (1)),
NULL, &tmpkey, &tmplen);
release_passphrase (pw);
if (rc)
@@ -985,11 +991,8 @@ export_p12_file (const char *fname)
kparms[7] = sk.u;
kparms[8] = NULL;
- pw = get_new_passphrase (3);
- if (!pw)
- key = NULL;
- else
- key = p12_build (kparms, cert, certlen, pw, opt_p12_charset, &keylen);
+ pw = get_passphrase (3);
+ key = p12_build (kparms, cert, certlen, pw, opt_p12_charset, &keylen);
release_passphrase (pw);
xfree (cert);
for (i=0; i < 8; i++)
@@ -1005,54 +1008,6 @@ export_p12_file (const char *fname)
}
-
-/* Do the percent and plus/space unescaping in place and return the
- length of the valid buffer. */
-static size_t
-percent_plus_unescape (unsigned char *string)
-{
- unsigned char *p = string;
- size_t n = 0;
-
- while (*string)
- {
- if (*string == '%' && string[1] && string[2])
- {
- string++;
- *p++ = xtoi_2 (string);
- n++;
- string+= 2;
- }
- else if (*string == '+')
- {
- *p++ = ' ';
- n++;
- string++;
- }
- else
- {
- *p++ = *string++;
- n++;
- }
- }
-
- return n;
-}
-
-/* Remove percent and plus escaping and make sure that the reuslt is a
- string. This is done in place. Returns STRING. */
-static char *
-percent_plus_unescape_string (char *string)
-{
- unsigned char *p = (unsigned char*)string;
- size_t n;
-
- n = percent_plus_unescape (p);
- p[n] = 0;
-
- return string;
-}
-
int
main (int argc, char **argv )
@@ -1094,6 +1049,8 @@ main (int argc, char **argv )
case oCanonical: opt_canonical=1; break;
case oHomedir: opt_homedir = pargs.r.ret_str; break;
+ case oAgentProgram: opt_agent_program = pargs.r.ret_str; break;
+
case oProtect: cmd = oProtect; break;
case oUnprotect: cmd = oUnprotect; break;
case oShadow: cmd = oShadow; break;
@@ -1111,11 +1068,11 @@ main (int argc, char **argv )
case oPrompt: opt_prompt = pargs.r.ret_str; break;
case oStatusMsg: opt_status_msg = 1; break;
- default : pargs.err = 2; break;
+ default: pargs.err = ARGPARSE_PRINT_ERROR; break;
}
}
- if (log_get_errorcount(0))
- exit(2);
+ if (log_get_errorcount (0))
+ exit (2);
fname = "-";
if (argc == 1)
@@ -1123,15 +1080,15 @@ main (int argc, char **argv )
else if (argc > 1)
usage (1);
- /* Tell simple-pwquery about the the standard socket name. */
- {
- char *tmp = make_filename (opt_homedir, "S.gpg-agent", NULL);
- simple_pw_set_socket (tmp);
- xfree (tmp);
- }
+ /* Set the information which can't be taken from envvars. */
+ gnupg_prepare_get_passphrase (GPG_ERR_SOURCE_DEFAULT,
+ opt.verbose,
+ opt_homedir,
+ opt_agent_program,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (opt_prompt)
- opt_prompt = percent_plus_unescape_string (xstrdup (opt_prompt));
+ opt_prompt = percent_plus_unescape (opt_prompt, 0);
if (cmd == oProtect)
read_and_protect (fname);
@@ -1169,102 +1126,65 @@ agent_exit (int rc)
2 = for unprotecting a pkcs#12 object
3 = for protecting a new pkcs#12 object
4 = for protecting an imported pkcs#12 in our system
- 5 = reenter the passphrase
- When adding 100 to the values, a "does not match - try again" error
- message is shown.
*/
static char *
-get_passphrase (int promptno, int opt_check)
+get_passphrase (int promptno)
{
char *pw;
int err;
const char *desc;
char *orig_codeset;
- int error_msgno;
+ int repeat = 0;
if (opt_passphrase)
return xstrdup (opt_passphrase);
- error_msgno = promptno / 100;
- promptno %= 100;
-
orig_codeset = i18n_switchto_utf8 ();
if (promptno == 1 && opt_prompt)
- desc = opt_prompt;
+ {
+ desc = opt_prompt;
+ }
else if (promptno == 2)
- desc = _("Please enter the passphrase to unprotect the "
- "PKCS#12 object.");
+ {
+ desc = _("Please enter the passphrase to unprotect the "
+ "PKCS#12 object.");
+ }
else if (promptno == 3)
- desc = _("Please enter the passphrase to protect the "
- "new PKCS#12 object.");
+ {
+ desc = _("Please enter the passphrase to protect the "
+ "new PKCS#12 object.");
+ repeat = 1;
+ }
else if (promptno == 4)
- desc = _("Please enter the passphrase to protect the "
- "imported object within the GnuPG system.");
- else if (promptno == 5)
- desc = _("Please re-enter this passphrase");
+ {
+ desc = _("Please enter the passphrase to protect the "
+ "imported object within the GnuPG system.");
+ repeat = 1;
+ }
else
desc = _("Please enter the passphrase or the PIN\n"
"needed to complete this operation.");
- pw = simple_pwquery (NULL,
- error_msgno == 1? _("does not match - try again"):NULL,
- _("Passphrase:"), desc, opt_check, &err);
- err = map_spwq_error (err);
-
i18n_switchback (orig_codeset);
- if (!pw)
+ err = gnupg_get_passphrase (NULL, NULL, _("Passphrase:"), desc,
+ repeat, repeat, 1, &pw);
+ if (err)
{
- if (err)
+ if (gpg_err_code (err) == GPG_ERR_CANCELED)
+ log_info (_("cancelled\n"));
+ else
log_error (_("error while asking for the passphrase: %s\n"),
gpg_strerror (err));
- else
- log_info (_("cancelled\n"));
agent_exit (0);
}
+ assert (pw);
return pw;
}
-/* Same as get_passphrase but requests it a second time and compares
- it to the one entered the first time. */
-static char *
-get_new_passphrase (int promptno)
-{
- char *pw;
- int i, secondpromptno;
-
- pw = get_passphrase (promptno, 1);
- if (!pw)
- return NULL; /* Canceled. */
- if (!*pw)
- return pw; /* Empty passphrase - no need to ask for repeating it. */
-
- secondpromptno = 5;
- for (i=0; i < 3; i++)
- {
- char *pw2 = get_passphrase (secondpromptno, 0);
- if (!pw2)
- {
- xfree (pw);
- return NULL; /* Canceled. */
- }
- if (!strcmp (pw, pw2))
- {
- xfree (pw2);
- return pw; /* Okay. */
- }
- secondpromptno = 105;
- xfree (pw2);
- }
- xfree (pw);
- return NULL; /* 3 times repeated wrong - cancel. */
-}
-
-
-
static void
release_passphrase (char *pw)
{
diff --git a/common/ChangeLog b/common/ChangeLog
index 1cf4f50fc..af804f490 100644
--- a/common/ChangeLog
+++ b/common/ChangeLog
@@ -1,3 +1,22 @@
+2009-04-01 Werner Koch <wk@g10code.com>
+
+ * exechelp.c (gnupg_spawn_process): Implement new flag bit 6.
+ * sysutils.c (gnupg_allow_set_foregound_window): Allow the use of
+ ASFW_ANY.
+
+ * membuf.c (put_membuf, get_membuf): Wipe memory on out of core.
+
+2009-03-31 Werner Koch <wk@g10code.com>
+
+ * percent.c (percent_unescape, percent_plus_unescape): New.
+ (percent_plus_unescape_inplace, percent_unescape_inplace): New.
+ (do_plus_or_plain_unescape, count_unescape, do_unescape): New.
+ (do_unescape_inplace): New.
+ * t-percent.c (test_percent_plus_escape): Test percent_plus_unescape.
+
+ * get-passphrase.c, get-passphrase.h: New.
+ * Makefile.am (without_pth_sources): New.
+
2009-03-18 Werner Koch <wk@g10code.com>
* exechelp.c: Include sys/resource.h and sys/stat.h.
diff --git a/common/Makefile.am b/common/Makefile.am
index 72c7d179f..2ef324e18 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -71,9 +71,12 @@ common_sources = \
localename.c \
helpfile.c
+# Sources only useful without PTH.
+without_pth_sources = \
+ get-passphrase.c get-passphrase.h
-libcommon_a_SOURCES = $(common_sources)
+libcommon_a_SOURCES = $(common_sources) $(without_pth_sources)
if USE_DNS_SRV
libcommon_a_SOURCES += srv.c
endif
diff --git a/common/exechelp.c b/common/exechelp.c
index 3d1136609..7019ae7a0 100644
--- a/common/exechelp.c
+++ b/common/exechelp.c
@@ -52,6 +52,7 @@
#include "util.h"
#include "i18n.h"
+#include "sysutils.h"
#include "exechelp.h"
/* Define to 1 do enable debugging. */
@@ -471,6 +472,10 @@ gnupg_create_inbound_pipe (int filedes[2])
This flag is only useful under W32 systems, so that no new
console is created and pops up a console window when
starting the server
+
+ Bit 6: On W32 run AllowSetForegroundWindow for the child. Due to
+ error problems this actually allows SetForegroundWindow for
+ childs of this process.
Returns 0 on success or an error code. */
gpg_error_t
@@ -568,6 +573,12 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
/* " dwProcessID=%d dwThreadId=%d\n", */
/* pi.hProcess, pi.hThread, */
/* (int) pi.dwProcessId, (int) pi.dwThreadId); */
+
+ /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
+ invalid argument error if we pass the the correct processID to
+ it. As a workaround we use -1 (ASFW_ANY). */
+ if ( (flags & 64) )
+ gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);
/* Process has been created suspended; resume it now. */
ResumeThread (pi.hThread);
diff --git a/common/get-passphrase.c b/common/get-passphrase.c
new file mode 100644
index 000000000..68d7b706a
--- /dev/null
+++ b/common/get-passphrase.c
@@ -0,0 +1,277 @@
+/* get-passphrase.c - Ask for a passphrase via the agent
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <assuan.h>
+
+#include "util.h"
+#include "i18n.h"
+#include "asshelp.h"
+#include "membuf.h"
+#include "sysutils.h"
+#include "get-passphrase.h"
+
+/* The context used by this process to ask for the passphrase. */
+static assuan_context_t agent_ctx;
+static struct
+{
+ gpg_err_source_t errsource;
+ int verbosity;
+ const char *homedir;
+ const char *agent_program;
+ const char *display;
+ const char *ttyname;
+ const char *ttytype;
+ const char *lc_ctype;
+ const char *lc_messages;
+ const char *xauthority;
+ const char *pinentry_user_data;
+} agentargs;
+
+
+/* Set local variable to be used for a possible agent startup. Note
+ that the strings are just pointers and should not anymore be
+ modified by the caller. */
+void
+gnupg_prepare_get_passphrase (gpg_err_source_t errsource,
+ int verbosity,
+ const char *homedir,
+ const char *agent_program,
+ const char *opt_display,
+ const char *opt_ttyname,
+ const char *opt_ttytype,
+ const char *opt_lc_ctype,
+ const char *opt_lc_messages,
+ const char *opt_xauthority,
+ const char *opt_pinentry_user_data)
+{
+ agentargs.errsource = errsource;
+ agentargs.verbosity = verbosity;
+ agentargs.homedir = homedir;
+ agentargs.agent_program = agent_program;
+ agentargs.display = opt_display;
+ agentargs.ttyname = opt_ttyname;
+ agentargs.ttytype = opt_ttytype;
+ agentargs.lc_ctype = opt_lc_ctype;
+ agentargs.lc_messages = opt_lc_messages;
+ agentargs.xauthority = opt_xauthority;
+ agentargs.pinentry_user_data = opt_pinentry_user_data;
+}
+
+
+/* Try to connect to the agent via socket or fork it off and work by
+ pipes. Handle the server's initial greeting. */
+static gpg_error_t
+start_agent (void)
+{
+ gpg_error_t err;
+
+ /* Fixme: This code is not thread safe, thus we don't build it with
+ pth. We will need a context for each thread or serialize the
+ access to the agent. */
+ if (agent_ctx)
+ return 0;
+
+ err = start_new_gpg_agent (&agent_ctx,
+ agentargs.errsource,
+ agentargs.homedir,
+ agentargs.agent_program,
+ agentargs.display,
+ agentargs.ttyname,
+ agentargs.ttytype,
+ agentargs.lc_ctype,
+ agentargs.lc_messages,
+ agentargs.xauthority,
+ agentargs.pinentry_user_data,
+ agentargs.verbosity, 0, NULL, NULL);
+ if (!err)
+ {
+ /* Tell the agent that we support Pinentry notifications. No
+ error checking so that it will work with older agents. */
+ assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+
+ return err;
+}
+
+
+/* This is the default inquiry callback. It merely handles the
+ Pinentry notification. */
+static int
+default_inq_cb (void *opaque, const char *line)
+{
+ (void)opaque;
+
+ if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
+ {
+ gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
+ /* We do not return errors to avoid breaking other code. */
+ }
+ else
+ log_debug ("ignoring gpg-agent inquiry `%s'\n", line);
+
+ return 0;
+}
+
+
+static int
+membuf_data_cb (void *opaque, const void *buffer, size_t length)
+{
+ membuf_t *data = opaque;
+
+ if (buffer)
+ put_membuf (data, buffer, length);
+ return 0;
+}
+
+
+/* Ask for a passphrase via gpg-agent. On success the caller needs to
+ free the string stored at R_PASSPHRASE. On error NULL will be
+ stored at R_PASSPHRASE and an appropriate gpg error code is
+ returned. With REPEAT set to 1, gpg-agent will ask the user to
+ repeat the just entered passphrase. CACHE_ID is a gpg-agent style
+ passphrase cache id or NULL. ERR_MSG is a error message to be
+ presented to the user (e.g. "bad passphrase - try again") or NULL.
+ PROMPT is the prompt string to label the entry box, it may be NULL
+ for a default one. DESC_MSG is a longer description to be
+ displayed above the entry box, if may be NULL for a default one.
+ If USE_SECMEM is true, the returned passphrase is retruned in
+ secure memory. The length of all these strings is limited; they
+ need to fit in their encoded form into a standard Assuan line (i.e
+ less then about 950 characters). All strings shall be UTF-8. */
+gpg_error_t
+gnupg_get_passphrase (const char *cache_id,
+ const char *err_msg,
+ const char *prompt,
+ const char *desc_msg,
+ int repeat,
+ int check_quality,
+ int use_secmem,
+ char **r_passphrase)
+{
+ gpg_error_t err;
+ char line[ASSUAN_LINELENGTH];
+ const char *arg1 = NULL;
+ char *arg2 = NULL;
+ char *arg3 = NULL;
+ char *arg4 = NULL;
+ membuf_t data;
+
+ *r_passphrase = NULL;
+
+ err = start_agent ();
+ if (err)
+ return err;
+
+ /* 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);
+
+ arg1 = cache_id && *cache_id? cache_id:NULL;
+ if (err_msg && *err_msg)
+ if (!(arg2 = percent_plus_escape (err_msg)))
+ goto no_mem;
+ if (prompt && *prompt)
+ if (!(arg3 = percent_plus_escape (prompt)))
+ goto no_mem;
+ if (desc_msg && *desc_msg)
+ if (!(arg4 = percent_plus_escape (desc_msg)))
+ goto no_mem;
+
+ snprintf (line, DIM(line)-1,
+ "GET_PASSPHRASE --data %s--repeat=%d -- %s %s %s %s",
+ check_quality? "--check ":"",
+ repeat,
+ arg1? arg1:"X",
+ arg2? arg2:"X",
+ arg3? arg3:"X",
+ arg4? arg4:"X");
+ line[DIM(line)-1] = 0;
+ xfree (arg2);
+ xfree (arg3);
+ xfree (arg4);
+
+ if (use_secmem)
+ init_membuf_secure (&data, 64);
+ else
+ init_membuf (&data, 64);
+ err = assuan_transact (agent_ctx, line,
+ membuf_data_cb, &data,
+ default_inq_cb, NULL, NULL, NULL);
+
+ /* Older Pinentries return the old assuan error code for canceled
+ which gets translated bt libassuan to GPG_ERR_ASS_CANCELED and
+ not to the code for a user cancel. Fix this here. */
+ if (err && gpg_err_source (err)
+ && gpg_err_code (err) == GPG_ERR_ASS_CANCELED)
+ err = gpg_err_make (gpg_err_source (err), GPG_ERR_CANCELED);
+
+ if (err)
+ {
+ void *p;
+ size_t n;
+
+ p = get_membuf (&data, &n);
+ if (p)
+ wipememory (p, n);
+ xfree (p);
+ }
+ else
+ {
+ put_membuf (&data, "", 1);
+ *r_passphrase = get_membuf (&data, NULL);
+ if (!*r_passphrase)
+ err = gpg_error_from_syserror ();
+ }
+ return err;
+ no_mem:
+ err = gpg_error_from_syserror ();
+ xfree (arg2);
+ xfree (arg3);
+ xfree (arg4);
+ return err;
+}
+
+
+/* Flush the passphrase cache with Id CACHE_ID. */
+gpg_error_t
+gnupg_clear_passphrase (const char *cache_id)
+{
+ gpg_error_t err;
+ char line[ASSUAN_LINELENGTH];
+
+ if (!cache_id || !*cache_id)
+ return 0;
+
+ err = start_agent ();
+ if (err)
+ return err;
+
+ snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
+ line[DIM(line)-1] = 0;
+ return assuan_transact (agent_ctx, line, NULL, NULL,
+ default_inq_cb, NULL, NULL, NULL);
+}
diff --git a/common/get-passphrase.h b/common/get-passphrase.h
new file mode 100644
index 000000000..9457cdd3a
--- /dev/null
+++ b/common/get-passphrase.h
@@ -0,0 +1,47 @@
+/* get-passphrase.h - Definitions to ask for a passphrase via the agent.
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GNUPG_COMMON_GET_PASSPHRASE_H
+#define GNUPG_COMMON_GET_PASSPHRASE_H
+
+void gnupg_prepare_get_passphrase (gpg_err_source_t errsource,
+ int verbosity,
+ const char *homedir,
+ const char *agent_program,
+ const char *opt_display,
+ const char *opt_ttyname,
+ const char *opt_ttytype,
+ const char *opt_lc_ctype,
+ const char *opt_lc_messages,
+ const char *opt_xauthority,
+ const char *opt_pinentry_user_data);
+
+gpg_error_t gnupg_get_passphrase (const char *cache_id,
+ const char *err_msg,
+ const char *prompt,
+ const char *desc_msg,
+ int repeat,
+ int check_quality,
+ int use_secmem,
+ char **r_passphrase);
+
+gpg_error_t gnupg_clear_passphrase (const char *cache_id);
+
+
+#endif /*GNUPG_COMMON_GET_PASSPHRASE_H*/
diff --git a/common/membuf.c b/common/membuf.c
index 9395eab6d..737930b76 100644
--- a/common/membuf.c
+++ b/common/membuf.c
@@ -1,5 +1,5 @@
-/* membuf.c - A simple implementation of a dynamic buffer
- * Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+/* membuf.c - A simple implementation of a dynamic buffer.
+ * Copyright (C) 2001, 2003, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -75,7 +75,7 @@ put_membuf (membuf_t *mb, const void *buf, size_t len)
in case we are storing sensitive data here. The membuf
API does not provide another way to cleanup after an
error. */
- memset (mb->buf, 0, mb->len);
+ wipememory (mb->buf, mb->len);
return;
}
mb->buf = p;
@@ -99,8 +99,12 @@ get_membuf (membuf_t *mb, size_t *len)
if (mb->out_of_core)
{
- xfree (mb->buf);
- mb->buf = NULL;
+ if (mb->buf)
+ {
+ wipememory (mb->buf, mb->len);
+ xfree (mb->buf);
+ mb->buf = NULL;
+ }
errno = mb->out_of_core;
return NULL;
}
diff --git a/common/percent.c b/common/percent.c
index a0c78ec7b..e0c359289 100644
--- a/common/percent.c
+++ b/common/percent.c
@@ -1,5 +1,5 @@
/* percent.c - Percent escaping
- * Copyright (C) 2008 Free Software Foundation, Inc.
+ * Copyright (C) 2008, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
+#include <assert.h>
#include "util.h"
@@ -74,3 +75,155 @@ percent_plus_escape (const char *string)
return buffer;
}
+
+
+/* Do the percent and plus/space unescaping from STRING to BUFFER and
+ return the length of the valid buffer. Plus unescaping is only
+ done if WITHPLUS is true. An escaped Nul character will be
+ replaced by NULREPL. */
+static size_t
+do_unescape (unsigned char *buffer, const unsigned char *string,
+ int withplus, int nulrepl)
+{
+ unsigned char *p = buffer;
+
+ while (*string)
+ {
+ if (*string == '%' && string[1] && string[2])
+ {
+ string++;
+ *p = xtoi_2 (string);
+ if (!*p)
+ *p = nulrepl;
+ string++;
+ }
+ else if (*string == '+' && withplus)
+ *p = ' ';
+ else
+ *p = *string;
+ p++;
+ string++;
+ }
+
+ return (p - buffer);
+}
+
+
+/* Count space required after unescaping STRING. Note that this will
+ never be larger than strlen (STRING). */
+static size_t
+count_unescape (const unsigned char *string)
+{
+ size_t n = 0;
+
+ while (*string)
+ {
+ if (*string == '%' && string[1] && string[2])
+ {
+ string++;
+ string++;
+ }
+ string++;
+ n++;
+ }
+
+ return n;
+}
+
+
+/* Helper. */
+static char *
+do_plus_or_plain_unescape (const char *string, int withplus, int nulrepl)
+{
+ size_t nbytes, n;
+ char *newstring;
+
+ nbytes = count_unescape (string);
+ newstring = xtrymalloc (nbytes+1);
+ if (newstring)
+ {
+ n = do_unescape (newstring, string, withplus, nulrepl);
+ assert (n == nbytes);
+ newstring[n] = 0;
+ }
+ return newstring;
+}
+
+
+/* Create a new allocated string from STRING with all "%xx" sequences
+ decoded and all plus signs replaced by a space. Embedded Nul
+ characters are replaced by the value of NULREPL. The function
+ returns the new string or NULL in case of a malloc failure. */
+char *
+percent_plus_unescape (const char *string, int nulrepl)
+{
+ return do_plus_or_plain_unescape (string, 1, nulrepl);
+}
+
+
+/* Create a new allocated string from STRING with all "%xx" sequences
+ decoded. Embedded Nul characters are replaced by the value of
+ NULREPL. The function returns the new string or NULL in case of a
+ malloc failure. */
+char *
+percent_unescape (const char *string, int nulrepl)
+{
+ return do_plus_or_plain_unescape (string, 0, nulrepl);
+}
+
+
+static size_t
+do_unescape_inplace (char *string, int withplus, int nulrepl)
+{
+ unsigned char *p, *p0;
+
+ p = p0 = string;
+ while (*string)
+ {
+ if (*string == '%' && string[1] && string[2])
+ {
+ string++;
+ *p = xtoi_2 (string);
+ if (!*p)
+ *p = nulrepl;
+ string++;
+ }
+ else if (*string == '+' && withplus)
+ *p = ' ';
+ else
+ *p = *string;
+ p++;
+ string++;
+ }
+
+ return (p - p0);
+}
+
+
+/* Perform percent and plus unescaping in STRING and return the new
+ valid length of the string. Embedded Nul characters are replaced
+ by the value of NULREPL. A terminating Nul character is not
+ inserted; the caller might want to call this function this way:
+
+ foo[percent_plus_unescape_inplace (foo, 0)] = 0;
+ */
+size_t
+percent_plus_unescape_inplace (char *string, int nulrepl)
+{
+ return do_unescape_inplace (string, 1, nulrepl);
+}
+
+
+/* Perform percent unescaping in STRING and return the new valid
+ length of the string. Embedded Nul characters are replaced by the
+ value of NULREPL. A terminating Nul character is not inserted; the
+ caller might want to call this function this way:
+
+ foo[percent_unescape_inplace (foo, 0)] = 0;
+ */
+size_t
+percent_unescape_inplace (char *string, int nulrepl)
+{
+ return do_unescape_inplace (string, 0, nulrepl);
+}
+
diff --git a/common/sysutils.c b/common/sysutils.c
index 0f1857ee3..8e0c75c1a 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -471,7 +471,9 @@ gnupg_reopen_std (const char *pgmname)
if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
exit (3);
-#endif /* HAVE_STAT && !HAVE_W32_SYSTEM */
+#else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
+ (void)pgmname;
+#endif
}
@@ -479,11 +481,11 @@ gnupg_reopen_std (const char *pgmname)
void
gnupg_allow_set_foregound_window (pid_t pid)
{
- if (!pid || pid == (pid_t)(-1))
+ if (!pid)
log_info ("%s called with invalid pid %lu\n",
"gnupg_allow_set_foregound_window", (unsigned long)pid);
#ifdef HAVE_W32_SYSTEM
- else if (!AllowSetForegroundWindow (pid))
+ else if (!AllowSetForegroundWindow ((pid_t)pid == (pid_t)(-1)?ASFW_ANY:pid))
log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
(unsigned long)pid, w32_strerror (-1));
#endif
diff --git a/common/t-percent.c b/common/t-percent.c
index 93d95f78d..b8641b90b 100644
--- a/common/t-percent.c
+++ b/common/t-percent.c
@@ -66,8 +66,9 @@ test_percent_plus_escape (void)
"%0A+ABC%09"
}, { NULL, NULL }
};
- char *buf;
+ char *buf, *buf2;
int i;
+ size_t len;
for (i=0; tbl[i].string; i++)
{
@@ -79,17 +80,34 @@ test_percent_plus_escape (void)
}
if (strcmp (buf, tbl[i].expect))
fail (i);
+ buf2 = percent_plus_unescape (buf, 0);
+ if (!buf2)
+ {
+ fprintf (stderr, "out of core: %s\n", strerror (errno));
+ exit (2);
+ }
+ if (strcmp (buf2, tbl[i].string))
+ fail (i);
+ xfree (buf2);
+ /* Now test the inplace conversion. */
+ len = percent_plus_unescape_inplace (buf, 0);
+ buf[len] = 0;
+ if (strcmp (buf, tbl[i].string))
+ fail (i);
xfree (buf);
}
}
+
int
main (int argc, char **argv)
{
(void)argc;
(void)argv;
+ /* FIXME: We escape_unescape is not tested - only
+ percent_plus_unescape. */
test_percent_plus_escape ();
return 0;
diff --git a/common/util.h b/common/util.h
index 3c664cec7..c64db9f6b 100644
--- a/common/util.h
+++ b/common/util.h
@@ -204,6 +204,11 @@ char *hex2str_alloc (const char *hexstring, size_t *r_count);
/*-- percent.c --*/
char *percent_plus_escape (const char *string);
+char *percent_plus_unescape (const char *string, int nulrepl);
+char *percent_unescape (const char *string, int nulrepl);
+
+size_t percent_plus_unescape_inplace (char *string, int nulrepl);
+size_t percent_unescape_inplace (char *string, int nulrepl);
/*-- homedir.c --*/
diff --git a/g10/ChangeLog b/g10/ChangeLog
index d7db690fc..50dca45ca 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,11 @@
+2009-03-31 Werner Koch <wk@g10code.com>
+
+ * passphrase.c (ask_passphrase): Use percent_plus_unescape.
+ * misc.c (unescape_percent_string): Remove.
+
+ * call-agent.c (unescape_status_string): Chnage to use
+ percent_plus_unescape.
+
2009-03-25 Werner Koch <wk@g10code.com>
* mainproc.c (print_pkenc_list): Use snprintf.
diff --git a/g10/call-agent.c b/g10/call-agent.c
index b6c61aa0e..444048a47 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -116,32 +116,7 @@ start_agent (void)
static char *
unescape_status_string (const unsigned char *s)
{
- char *buffer, *d;
-
- buffer = d = xtrymalloc (strlen (s)+1);
- if (!buffer)
- return NULL;
- while (*s)
- {
- if (*s == '%' && s[1] && s[2])
- {
- s++;
- *d = xtoi_2 (s);
- if (!*d)
- *d = '\xff';
- d++;
- s += 2;
- }
- else if (*s == '+')
- {
- *d++ = ' ';
- s++;
- }
- else
- *d++ = *s++;
- }
- *d = 0;
- return buffer;
+ return percent_plus_unescape (s, 0xff);
}
diff --git a/g10/main.h b/g10/main.h
index 706162529..1e5cad4bf 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -135,7 +135,6 @@ char *optsep(char **stringp);
char *argsplit(char *string);
int parse_options(char *str,unsigned int *options,
struct parse_options *opts,int noisy);
-char *unescape_percent_string (const unsigned char *s);
int has_invalid_email_chars (const char *s);
int is_valid_mailbox (const char *name);
const char *get_libexecdir (void);
diff --git a/g10/misc.c b/g10/misc.c
index b0e5e2ce1..80a8a74ca 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -1215,39 +1215,6 @@ parse_options(char *str,unsigned int *options,
}
-/* Return a new malloced string by unescaping the string S. Escaping
- is percent escaping and '+'/space mapping. A binary nul will
- silently be replaced by a 0xFF. */
-char *
-unescape_percent_string (const unsigned char *s)
-{
- char *buffer, *d;
-
- buffer = d = xmalloc (strlen (s)+1);
- while (*s)
- {
- if (*s == '%' && s[1] && s[2])
- {
- s++;
- *d = xtoi_2 (s);
- if (!*d)
- *d = '\xff';
- d++;
- s += 2;
- }
- else if (*s == '+')
- {
- *d++ = ' ';
- s++;
- }
- else
- *d++ = *s++;
- }
- *d = 0;
- return buffer;
-}
-
-
/* Check whether the string has characters not valid in an RFC-822
address. To cope with OpenPGP we ignore allow non-ascii characters
so that for example umlauts are legal in an email address. An
diff --git a/g10/passphrase.c b/g10/passphrase.c
index 0950581c9..8b952f72a 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -453,8 +453,9 @@ ask_passphrase (const char *description,
{
if (strchr (description, '%'))
{
- char *tmp = unescape_percent_string
- ((const unsigned char*)description);
+ char *tmp = percent_plus_unescape (description, 0xff);
+ if (!tmp)
+ log_fatal(_("out of core\n"));
tty_printf ("\n%s\n", tmp);
xfree (tmp);
}
diff --git a/scd/ChangeLog b/scd/ChangeLog
index efd46fea9..534a7092b 100644
--- a/scd/ChangeLog
+++ b/scd/ChangeLog
@@ -1,3 +1,8 @@
+2009-03-31 Werner Koch <wk@g10code.com>
+
+ * command.c (percent_plus_unescape): Remove.
+ (cmd_setattr): Use percent_plus_unescape_inplace.
+
2009-03-30 Werner Koch <wk@g10code.com>
* app-nks.c (do_decipher): Make it work for TCOS 3.
diff --git a/scd/command.c b/scd/command.c
index 71081b26f..6c1cdd072 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -462,41 +462,6 @@ open_card (ctrl_t ctrl, const char *apptype)
}
-/* Do the percent and plus/space unescaping in place and return the
- length of the valid buffer. */
-static size_t
-percent_plus_unescape (unsigned char *string)
-{
- unsigned char *p = string;
- size_t n = 0;
-
- while (*string)
- {
- if (*string == '%' && string[1] && string[2])
- {
- string++;
- *p++ = xtoi_2 (string);
- n++;
- string+= 2;
- }
- else if (*string == '+')
- {
- *p++ = ' ';
- n++;
- string++;
- }
- else
- {
- *p++ = *string++;
- n++;
- }
- }
-
- return n;
-}
-
-
-
/* SERIALNO [APPTYPE]
Return the serial number of the card using a status reponse. This
@@ -1153,7 +1118,7 @@ cmd_setattr (assuan_context_t ctx, char *orig_line)
*line++ = 0;
while (spacep (line))
line++;
- nbytes = percent_plus_unescape ((unsigned char*)line);
+ nbytes = percent_plus_unescape_inplace (line, 0);
rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
(const unsigned char*)line, nbytes);
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 9f926cfc7..a988a200f 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,9 @@
+2009-04-01 Werner Koch <wk@g10code.com>
+
+ * export.c (popen_protect_tool): Add command line option
+ --agent-program and pass flag bit 6.
+ * import.c (popen_protect_tool): Ditto.
+
2009-03-26 Werner Koch <wk@g10code.com>
* gpgsm.c (main): s/def_digest_string/forced_digest_algo/ and
diff --git a/sm/export.c b/sm/export.c
index f8e23cec1..fcf1dccc1 100644
--- a/sm/export.c
+++ b/sm/export.c
@@ -574,13 +574,14 @@ popen_protect_tool (ctrl_t ctrl, const char *pgmname,
const char *prompt, const char *keygrip,
pid_t *pid)
{
- const char *argv[20];
+ const char *argv[22];
int i=0;
/* Make sure that the agent is running so that the protect tool is
able to ask for a passphrase. This has only an effect under W32
where the agent is started on demand; sending a NOP does not harm
- on other platforms. */
+ on other platforms. This is not really necessary anymore because
+ the protect tool does this now by itself; it does not harm either.*/
gpgsm_agent_send_nop (ctrl);
argv[i++] = "--homedir";
@@ -595,13 +596,18 @@ popen_protect_tool (ctrl_t ctrl, const char *pgmname,
argv[i++] = "--p12-charset";
argv[i++] = opt.p12_charset;
}
+ if (opt.agent_program)
+ {
+ argv[i++] = "--agent-program";
+ argv[i++] = opt.agent_program;
+ }
argv[i++] = "--",
argv[i++] = keygrip,
argv[i] = NULL;
assert (i < sizeof argv);
return gnupg_spawn_process (pgmname, argv, infile, outfile,
- setup_pinentry_env, 128,
+ setup_pinentry_env, (128|64),
statusfile, pid);
}
diff --git a/sm/import.c b/sm/import.c
index cb1922ed5..5e8b42971 100644
--- a/sm/import.c
+++ b/sm/import.c
@@ -463,13 +463,14 @@ static gpg_error_t
popen_protect_tool (ctrl_t ctrl, const char *pgmname,
FILE *infile, FILE *outfile, FILE **statusfile, pid_t *pid)
{
- const char *argv[20];
+ const char *argv[22];
int i=0;
/* Make sure that the agent is running so that the protect tool is
able to ask for a passphrase. This has only an effect under W32
where the agent is started on demand; sending a NOP does not harm
- on other platforms. */
+ on other platforms. This is not really necessary anymore because
+ the protect tool does this now by itself; it does not harm either. */
gpgsm_agent_send_nop (ctrl);
argv[i++] = "--homedir";
@@ -483,12 +484,17 @@ popen_protect_tool (ctrl_t ctrl, const char *pgmname,
argv[i++] = "--passphrase";
argv[i++] = opt.fixed_passphrase;
}
+ if (opt.agent_program)
+ {
+ argv[i++] = "--agent-program";
+ argv[i++] = opt.agent_program;
+ }
argv[i++] = "--",
argv[i] = NULL;
assert (i < sizeof argv);
return gnupg_spawn_process (pgmname, argv, infile, outfile,
- setup_pinentry_env, 128,
+ setup_pinentry_env, (128 | 64),
statusfile, pid);
}
diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c
index ba97c1a10..06dafd5c9 100644
--- a/tools/gpg-connect-agent.c
+++ b/tools/gpg-connect-agent.c
@@ -215,7 +215,7 @@ gnu_getcwd (void)
}
-/* Unescale STRING and returned the malloced result. The surrounding
+/* Unescape STRING and returned the malloced result. The surrounding
quotes must already be removed from STRING. */
static char *
unescape_string (const char *string)
diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
index 92016efc4..7ba526f69 100644
--- a/tools/gpgconf-comp.c
+++ b/tools/gpgconf-comp.c
@@ -1141,7 +1141,7 @@ my_dgettext (const char *domain, const char *msgid)
/* FIXME: we have no dgettext, thus we can't switch. */
- text = gettext (msgid);
+ text = (char*)gettext (msgid);
return text ? text : msgid;
}
#elif defined(ENABLE_NLS)