1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

Import/export of pkcs#12 now uses the gpg-agent directly.

Removed duplicated code (percent unescaping).
This commit is contained in:
Werner Koch 2009-04-01 10:51:53 +00:00
parent 98e1a75e20
commit f8b4cd7650
29 changed files with 716 additions and 369 deletions

3
NEWS
View File

@ -19,6 +19,9 @@ Noteworthy changes in version 2.0.12 (not released)
* Support for the Telesec Netkey 3 cards. * 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) Noteworthy changes in version 2.0.11 (2009-03-03)
------------------------------------------------- -------------------------------------------------

View File

@ -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> 2009-03-27 Werner Koch <wk@g10code.com>
* learncard.c (agent_handle_learn): Add new certtype 111. * learncard.c (agent_handle_learn): Add new certtype 111.

View File

@ -74,9 +74,9 @@ gpg_protect_tool_SOURCES = \
protect.c \ protect.c \
minip12.c minip12.h minip12.c minip12.h
# Needs $(NETLIBS) for libsimple-pwquery.la. gpg_protect_tool_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS)
gpg_protect_tool_LDADD = $(pwquery_libs) $(common_libs) \ gpg_protect_tool_LDADD = $(common_libs) $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) \
$(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(NETLIBS) $(LIBICONV) $(GPG_ERROR_LIBS) $(LIBINTL) $(NETLIBS) $(LIBICONV)
gpg_preset_passphrase_SOURCES = \ gpg_preset_passphrase_SOURCES = \
preset-passphrase.c preset-passphrase.c

View File

@ -105,6 +105,7 @@ static void
dump_mutex_state (pth_mutex_t *m) dump_mutex_state (pth_mutex_t *m)
{ {
#ifdef _W32_PTH_H #ifdef _W32_PTH_H
(void)m;
log_printf ("unknown under W32"); log_printf ("unknown under W32");
#else #else
if (!(m->mx_state & PTH_MUTEX_INITIALIZED)) if (!(m->mx_state & PTH_MUTEX_INITIALIZED))

View File

@ -136,6 +136,7 @@ static void
dump_mutex_state (pth_mutex_t *m) dump_mutex_state (pth_mutex_t *m)
{ {
#ifdef _W32_PTH_H #ifdef _W32_PTH_H
(void)m;
log_printf ("unknown under W32"); log_printf ("unknown under W32");
#else #else
if (!(m->mx_state & PTH_MUTEX_INITIALIZED)) if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
@ -561,43 +562,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 static int
learn_status_cb (void *opaque, const char *line) learn_status_cb (void *opaque, const char *line)
@ -1045,7 +1009,7 @@ card_getattr_cb (void *opaque, const char *line)
if (keywordlen == parm->keywordlen if (keywordlen == parm->keywordlen
&& !memcmp (keyword, parm->keyword, 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) if (!parm->data)
parm->error = errno; parm->error = errno;
} }

View File

@ -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 /* Parse a hex string. Return an Assuan error code or 0 on success and the
length of the parsed string in LEN. */ length of the parsed string in LEN. */
static int static int
@ -1494,7 +1458,7 @@ cmd_putval (assuan_context_t ctx, char *line)
p = strchr (value, ' '); p = strchr (value, ' ');
if (p) if (p)
*p = 0; *p = 0;
valuelen = percent_plus_unescape (value); valuelen = percent_plus_unescape_inplace (value, 0);
} }
} }
if (!key || !*key) if (!key || !*key)

View File

@ -41,13 +41,14 @@
#define JNLIB_NEED_LOG_LOGV #define JNLIB_NEED_LOG_LOGV
#include "agent.h" #include "agent.h"
#include "minip12.h" #include "minip12.h"
#include "simple-pwquery.h"
#include "i18n.h" #include "i18n.h"
#include "get-passphrase.h"
#include "sysutils.h" #include "sysutils.h"
enum cmd_and_opt_values enum cmd_and_opt_values
{ aNull = 0, {
aNull = 0,
oVerbose = 'v', oVerbose = 'v',
oArmor = 'a', oArmor = 'a',
oPassphrase = 'P', oPassphrase = 'P',
@ -72,17 +73,19 @@ enum cmd_and_opt_values
oPrompt, oPrompt,
oStatusMsg, oStatusMsg,
aTest }; oAgentProgram
};
struct rsa_secret_key_s struct rsa_secret_key_s
{ {
gcry_mpi_t n; /* public modulus */ gcry_mpi_t n; /* public modulus */
gcry_mpi_t e; /* public exponent */ gcry_mpi_t e; /* public exponent */
gcry_mpi_t d; /* exponent */ gcry_mpi_t d; /* exponent */
gcry_mpi_t p; /* prime p. */ gcry_mpi_t p; /* prime p. */
gcry_mpi_t q; /* prime q. */ gcry_mpi_t q; /* prime q. */
gcry_mpi_t u; /* inverse of p mod q. */ gcry_mpi_t u; /* inverse of p mod q. */
}; };
static const char *opt_homedir; static const char *opt_homedir;
@ -96,41 +99,51 @@ static const char *opt_passphrase;
static char *opt_prompt; static char *opt_prompt;
static int opt_status_msg; static int opt_status_msg;
static const char *opt_p12_charset; static const char *opt_p12_charset;
static const char *opt_agent_program;
static char *get_passphrase (int promptno, int opt_check); static char *get_passphrase (int promptno);
static char *get_new_passphrase (int promptno);
static void release_passphrase (char *pw); static void release_passphrase (char *pw);
static int store_private_key (const unsigned char *grip, static int store_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force); const void *buffer, size_t length, int force);
static ARGPARSE_OPTS opts[] = { 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 ") }, ARGPARSE_group (301, N_("@\nOptions:\n ")),
{ oVerbose, "verbose", 0, "verbose" }, ARGPARSE_s_n (oVerbose, "verbose", "verbose"),
{ oArmor, "armor", 0, "write output in advanced format" }, ARGPARSE_s_n (oArmor, "armor", "write output in advanced format"),
{ oCanonical, "canonical", 0, "write output in canonical format" }, ARGPARSE_s_n (oCanonical, "canonical", "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"}, ARGPARSE_s_s (oPassphrase, "passphrase", "|STRING|use passphrase STRING"),
{ oP12Export, "p12-export", 256, "export a private key pkcs#12 encoded"}, ARGPARSE_s_s (oP12Charset,"p12-charset",
{ oP12Charset,"p12-charset", 2, "|NAME|set charset for a new PKCS#12 passphrase to NAME"),
"|NAME|set charset for a new PKCS#12 passphrase to NAME" }, ARGPARSE_s_n (oHaveCert, "have-cert",
{ oHaveCert, "have-cert", 0, "certificate to export provided on STDIN"}, "certificate to export provided on STDIN"),
{ oStore, "store", 0, "store the created key in the appropriate place"}, ARGPARSE_s_n (oStore, "store",
{ oForce, "force", 0, "force overwriting"}, "store the created key in the appropriate place"),
{ oNoFailOnExist, "no-fail-on-exist", 0, "@" }, ARGPARSE_s_n (oForce, "force",
{ oHomedir, "homedir", 2, "@" }, "force overwriting"),
{ oPrompt, "prompt", 2, "|ESCSTRING|use ESCSTRING as prompt in pinentry"}, ARGPARSE_s_n (oNoFailOnExist, "no-fail-on-exist", "@"),
{ oStatusMsg, "enable-status-msg", 0, "@"}, ARGPARSE_s_s (oHomedir, "homedir", "@"),
ARGPARSE_s_s (oPrompt, "prompt",
"|ESCSTRING|use ESCSTRING as prompt in pinentry"),
ARGPARSE_s_n (oStatusMsg, "enable-status-msg", "@"),
{0} ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
ARGPARSE_end ()
}; };
static const char * static const char *
@ -158,9 +171,6 @@ my_strusage (int level)
} }
/* Include the implementation of map_spwq_error. */
MAP_SPWQ_ERROR_IMPL
/* static void */ /* static void */
/* print_mpi (const char *text, gcry_mpi_t a) */ /* print_mpi (const char *text, gcry_mpi_t a) */
/* { */ /* { */
@ -333,7 +343,7 @@ read_and_protect (const char *fname)
if (!key) if (!key)
return; return;
pw = get_passphrase (1, 0); pw = get_passphrase (1);
rc = agent_protect (key, pw, &result, &resultlen); rc = agent_protect (key, pw, &result, &resultlen);
release_passphrase (pw); release_passphrase (pw);
xfree (key); xfree (key);
@ -372,7 +382,7 @@ read_and_unprotect (const char *fname)
if (!key) if (!key)
return; return;
rc = agent_unprotect (key, (pw=get_passphrase (1, 0)), rc = agent_unprotect (key, (pw=get_passphrase (1)),
protected_at, &result, &resultlen); protected_at, &result, &resultlen);
release_passphrase (pw); release_passphrase (pw);
xfree (key); xfree (key);
@ -678,7 +688,7 @@ import_p12_file (const char *fname)
buf_off = 0; buf_off = 0;
kparms = p12_parse ((unsigned char*)buf+buf_off, buflen-buf_off, 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); import_p12_cert_cb, NULL);
release_passphrase (pw); release_passphrase (pw);
xfree (buf); xfree (buf);
@ -753,12 +763,8 @@ import_p12_file (const char *fname)
assert (buflen); assert (buflen);
gcry_sexp_release (s_key); gcry_sexp_release (s_key);
pw = get_passphrase (4);
pw = get_new_passphrase (4); rc = agent_protect (key, pw, &result, &resultlen);
if (!pw)
rc = gpg_error (GPG_ERR_CANCELED);
else
rc = agent_protect (key, pw, &result, &resultlen);
release_passphrase (pw); release_passphrase (pw);
xfree (key); xfree (key);
if (rc) if (rc)
@ -896,7 +902,7 @@ export_p12_file (const char *fname)
unsigned char *tmpkey; unsigned char *tmpkey;
size_t tmplen; size_t tmplen;
rc = agent_unprotect (key, (pw=get_passphrase (1, 0)), rc = agent_unprotect (key, (pw=get_passphrase (1)),
NULL, &tmpkey, &tmplen); NULL, &tmpkey, &tmplen);
release_passphrase (pw); release_passphrase (pw);
if (rc) if (rc)
@ -985,11 +991,8 @@ export_p12_file (const char *fname)
kparms[7] = sk.u; kparms[7] = sk.u;
kparms[8] = NULL; kparms[8] = NULL;
pw = get_new_passphrase (3); pw = get_passphrase (3);
if (!pw) key = p12_build (kparms, cert, certlen, pw, opt_p12_charset, &keylen);
key = NULL;
else
key = p12_build (kparms, cert, certlen, pw, opt_p12_charset, &keylen);
release_passphrase (pw); release_passphrase (pw);
xfree (cert); xfree (cert);
for (i=0; i < 8; i++) 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 int
main (int argc, char **argv ) main (int argc, char **argv )
@ -1094,6 +1049,8 @@ main (int argc, char **argv )
case oCanonical: opt_canonical=1; break; case oCanonical: opt_canonical=1; break;
case oHomedir: opt_homedir = pargs.r.ret_str; 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 oProtect: cmd = oProtect; break;
case oUnprotect: cmd = oUnprotect; break; case oUnprotect: cmd = oUnprotect; break;
case oShadow: cmd = oShadow; 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 oPrompt: opt_prompt = pargs.r.ret_str; break;
case oStatusMsg: opt_status_msg = 1; 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)) if (log_get_errorcount (0))
exit(2); exit (2);
fname = "-"; fname = "-";
if (argc == 1) if (argc == 1)
@ -1123,15 +1080,15 @@ main (int argc, char **argv )
else if (argc > 1) else if (argc > 1)
usage (1); usage (1);
/* Tell simple-pwquery about the the standard socket name. */ /* Set the information which can't be taken from envvars. */
{ gnupg_prepare_get_passphrase (GPG_ERR_SOURCE_DEFAULT,
char *tmp = make_filename (opt_homedir, "S.gpg-agent", NULL); opt.verbose,
simple_pw_set_socket (tmp); opt_homedir,
xfree (tmp); opt_agent_program,
} NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (opt_prompt) if (opt_prompt)
opt_prompt = percent_plus_unescape_string (xstrdup (opt_prompt)); opt_prompt = percent_plus_unescape (opt_prompt, 0);
if (cmd == oProtect) if (cmd == oProtect)
read_and_protect (fname); read_and_protect (fname);
@ -1169,102 +1126,65 @@ agent_exit (int rc)
2 = for unprotecting a pkcs#12 object 2 = for unprotecting a pkcs#12 object
3 = for protecting a new pkcs#12 object 3 = for protecting a new pkcs#12 object
4 = for protecting an imported pkcs#12 in our system 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 * static char *
get_passphrase (int promptno, int opt_check) get_passphrase (int promptno)
{ {
char *pw; char *pw;
int err; int err;
const char *desc; const char *desc;
char *orig_codeset; char *orig_codeset;
int error_msgno; int repeat = 0;
if (opt_passphrase) if (opt_passphrase)
return xstrdup (opt_passphrase); return xstrdup (opt_passphrase);
error_msgno = promptno / 100;
promptno %= 100;
orig_codeset = i18n_switchto_utf8 (); orig_codeset = i18n_switchto_utf8 ();
if (promptno == 1 && opt_prompt) if (promptno == 1 && opt_prompt)
desc = opt_prompt; {
desc = opt_prompt;
}
else if (promptno == 2) 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) 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) else if (promptno == 4)
desc = _("Please enter the passphrase to protect the " {
"imported object within the GnuPG system."); desc = _("Please enter the passphrase to protect the "
else if (promptno == 5) "imported object within the GnuPG system.");
desc = _("Please re-enter this passphrase"); repeat = 1;
}
else else
desc = _("Please enter the passphrase or the PIN\n" desc = _("Please enter the passphrase or the PIN\n"
"needed to complete this operation."); "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); 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"), log_error (_("error while asking for the passphrase: %s\n"),
gpg_strerror (err)); gpg_strerror (err));
else
log_info (_("cancelled\n"));
agent_exit (0); agent_exit (0);
} }
assert (pw);
return 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 static void
release_passphrase (char *pw) release_passphrase (char *pw)
{ {

View File

@ -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> 2009-03-18 Werner Koch <wk@g10code.com>
* exechelp.c: Include sys/resource.h and sys/stat.h. * exechelp.c: Include sys/resource.h and sys/stat.h.

View File

@ -71,9 +71,12 @@ common_sources = \
localename.c \ localename.c \
helpfile.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 if USE_DNS_SRV
libcommon_a_SOURCES += srv.c libcommon_a_SOURCES += srv.c
endif endif

View File

@ -52,6 +52,7 @@
#include "util.h" #include "util.h"
#include "i18n.h" #include "i18n.h"
#include "sysutils.h"
#include "exechelp.h" #include "exechelp.h"
/* Define to 1 do enable debugging. */ /* 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 This flag is only useful under W32 systems, so that no new
console is created and pops up a console window when console is created and pops up a console window when
starting the server 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. */ Returns 0 on success or an error code. */
gpg_error_t gpg_error_t
@ -568,6 +573,12 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
/* " dwProcessID=%d dwThreadId=%d\n", */ /* " dwProcessID=%d dwThreadId=%d\n", */
/* pi.hProcess, pi.hThread, */ /* pi.hProcess, pi.hThread, */
/* (int) pi.dwProcessId, (int) pi.dwThreadId); */ /* (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. */ /* Process has been created suspended; resume it now. */
ResumeThread (pi.hThread); ResumeThread (pi.hThread);

277
common/get-passphrase.c Normal file
View File

@ -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);
}

47
common/get-passphrase.h Normal file
View File

@ -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*/

View File

@ -1,5 +1,5 @@
/* membuf.c - A simple implementation of a dynamic buffer /* membuf.c - A simple implementation of a dynamic buffer.
* Copyright (C) 2001, 2003 Free Software Foundation, Inc. * Copyright (C) 2001, 2003, 2009 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * 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 in case we are storing sensitive data here. The membuf
API does not provide another way to cleanup after an API does not provide another way to cleanup after an
error. */ error. */
memset (mb->buf, 0, mb->len); wipememory (mb->buf, mb->len);
return; return;
} }
mb->buf = p; mb->buf = p;
@ -99,8 +99,12 @@ get_membuf (membuf_t *mb, size_t *len)
if (mb->out_of_core) if (mb->out_of_core)
{ {
xfree (mb->buf); if (mb->buf)
mb->buf = NULL; {
wipememory (mb->buf, mb->len);
xfree (mb->buf);
mb->buf = NULL;
}
errno = mb->out_of_core; errno = mb->out_of_core;
return NULL; return NULL;
} }

View File

@ -1,5 +1,5 @@
/* percent.c - Percent escaping /* 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. * This file is part of GnuPG.
* *
@ -21,6 +21,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <ctype.h> #include <ctype.h>
#include <assert.h>
#include "util.h" #include "util.h"
@ -74,3 +75,155 @@ percent_plus_escape (const char *string)
return buffer; 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);
}

View File

@ -471,7 +471,9 @@ gnupg_reopen_std (const char *pgmname)
if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2) if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
exit (3); 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 void
gnupg_allow_set_foregound_window (pid_t pid) 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", log_info ("%s called with invalid pid %lu\n",
"gnupg_allow_set_foregound_window", (unsigned long)pid); "gnupg_allow_set_foregound_window", (unsigned long)pid);
#ifdef HAVE_W32_SYSTEM #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", log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
(unsigned long)pid, w32_strerror (-1)); (unsigned long)pid, w32_strerror (-1));
#endif #endif

View File

@ -66,8 +66,9 @@ test_percent_plus_escape (void)
"%0A+ABC%09" "%0A+ABC%09"
}, { NULL, NULL } }, { NULL, NULL }
}; };
char *buf; char *buf, *buf2;
int i; int i;
size_t len;
for (i=0; tbl[i].string; i++) for (i=0; tbl[i].string; i++)
{ {
@ -79,17 +80,34 @@ test_percent_plus_escape (void)
} }
if (strcmp (buf, tbl[i].expect)) if (strcmp (buf, tbl[i].expect))
fail (i); 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); xfree (buf);
} }
} }
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
(void)argc; (void)argc;
(void)argv; (void)argv;
/* FIXME: We escape_unescape is not tested - only
percent_plus_unescape. */
test_percent_plus_escape (); test_percent_plus_escape ();
return 0; return 0;

View File

@ -204,6 +204,11 @@ char *hex2str_alloc (const char *hexstring, size_t *r_count);
/*-- percent.c --*/ /*-- percent.c --*/
char *percent_plus_escape (const char *string); 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 --*/ /*-- homedir.c --*/

View File

@ -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> 2009-03-25 Werner Koch <wk@g10code.com>
* mainproc.c (print_pkenc_list): Use snprintf. * mainproc.c (print_pkenc_list): Use snprintf.

View File

@ -116,32 +116,7 @@ start_agent (void)
static char * static char *
unescape_status_string (const unsigned char *s) unescape_status_string (const unsigned char *s)
{ {
char *buffer, *d; return percent_plus_unescape (s, 0xff);
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;
} }

View File

@ -135,7 +135,6 @@ char *optsep(char **stringp);
char *argsplit(char *string); char *argsplit(char *string);
int parse_options(char *str,unsigned int *options, int parse_options(char *str,unsigned int *options,
struct parse_options *opts,int noisy); struct parse_options *opts,int noisy);
char *unescape_percent_string (const unsigned char *s);
int has_invalid_email_chars (const char *s); int has_invalid_email_chars (const char *s);
int is_valid_mailbox (const char *name); int is_valid_mailbox (const char *name);
const char *get_libexecdir (void); const char *get_libexecdir (void);

View File

@ -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 /* Check whether the string has characters not valid in an RFC-822
address. To cope with OpenPGP we ignore allow non-ascii characters address. To cope with OpenPGP we ignore allow non-ascii characters
so that for example umlauts are legal in an email address. An so that for example umlauts are legal in an email address. An

View File

@ -453,8 +453,9 @@ ask_passphrase (const char *description,
{ {
if (strchr (description, '%')) if (strchr (description, '%'))
{ {
char *tmp = unescape_percent_string char *tmp = percent_plus_unescape (description, 0xff);
((const unsigned char*)description); if (!tmp)
log_fatal(_("out of core\n"));
tty_printf ("\n%s\n", tmp); tty_printf ("\n%s\n", tmp);
xfree (tmp); xfree (tmp);
} }

View File

@ -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> 2009-03-30 Werner Koch <wk@g10code.com>
* app-nks.c (do_decipher): Make it work for TCOS 3. * app-nks.c (do_decipher): Make it work for TCOS 3.

View File

@ -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] /* SERIALNO [APPTYPE]
Return the serial number of the card using a status reponse. This 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; *line++ = 0;
while (spacep (line)) while (spacep (line))
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, rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx,
(const unsigned char*)line, nbytes); (const unsigned char*)line, nbytes);

View File

@ -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> 2009-03-26 Werner Koch <wk@g10code.com>
* gpgsm.c (main): s/def_digest_string/forced_digest_algo/ and * gpgsm.c (main): s/def_digest_string/forced_digest_algo/ and

View File

@ -574,13 +574,14 @@ popen_protect_tool (ctrl_t ctrl, const char *pgmname,
const char *prompt, const char *keygrip, const char *prompt, const char *keygrip,
pid_t *pid) pid_t *pid)
{ {
const char *argv[20]; const char *argv[22];
int i=0; int i=0;
/* Make sure that the agent is running so that the protect tool is /* 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 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 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); gpgsm_agent_send_nop (ctrl);
argv[i++] = "--homedir"; argv[i++] = "--homedir";
@ -595,13 +596,18 @@ popen_protect_tool (ctrl_t ctrl, const char *pgmname,
argv[i++] = "--p12-charset"; argv[i++] = "--p12-charset";
argv[i++] = opt.p12_charset; argv[i++] = opt.p12_charset;
} }
if (opt.agent_program)
{
argv[i++] = "--agent-program";
argv[i++] = opt.agent_program;
}
argv[i++] = "--", argv[i++] = "--",
argv[i++] = keygrip, argv[i++] = keygrip,
argv[i] = NULL; argv[i] = NULL;
assert (i < sizeof argv); assert (i < sizeof argv);
return gnupg_spawn_process (pgmname, argv, infile, outfile, return gnupg_spawn_process (pgmname, argv, infile, outfile,
setup_pinentry_env, 128, setup_pinentry_env, (128|64),
statusfile, pid); statusfile, pid);
} }

View File

@ -463,13 +463,14 @@ static gpg_error_t
popen_protect_tool (ctrl_t ctrl, const char *pgmname, popen_protect_tool (ctrl_t ctrl, const char *pgmname,
FILE *infile, FILE *outfile, FILE **statusfile, pid_t *pid) FILE *infile, FILE *outfile, FILE **statusfile, pid_t *pid)
{ {
const char *argv[20]; const char *argv[22];
int i=0; int i=0;
/* Make sure that the agent is running so that the protect tool is /* 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 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 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); gpgsm_agent_send_nop (ctrl);
argv[i++] = "--homedir"; argv[i++] = "--homedir";
@ -483,12 +484,17 @@ popen_protect_tool (ctrl_t ctrl, const char *pgmname,
argv[i++] = "--passphrase"; argv[i++] = "--passphrase";
argv[i++] = opt.fixed_passphrase; argv[i++] = opt.fixed_passphrase;
} }
if (opt.agent_program)
{
argv[i++] = "--agent-program";
argv[i++] = opt.agent_program;
}
argv[i++] = "--", argv[i++] = "--",
argv[i] = NULL; argv[i] = NULL;
assert (i < sizeof argv); assert (i < sizeof argv);
return gnupg_spawn_process (pgmname, argv, infile, outfile, return gnupg_spawn_process (pgmname, argv, infile, outfile,
setup_pinentry_env, 128, setup_pinentry_env, (128 | 64),
statusfile, pid); statusfile, pid);
} }

View File

@ -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. */ quotes must already be removed from STRING. */
static char * static char *
unescape_string (const char *string) unescape_string (const char *string)

View File

@ -1141,7 +1141,7 @@ my_dgettext (const char *domain, const char *msgid)
/* FIXME: we have no dgettext, thus we can't switch. */ /* FIXME: we have no dgettext, thus we can't switch. */
text = gettext (msgid); text = (char*)gettext (msgid);
return text ? text : msgid; return text ? text : msgid;
} }
#elif defined(ENABLE_NLS) #elif defined(ENABLE_NLS)