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:
parent
98e1a75e20
commit
f8b4cd7650
3
NEWS
3
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)
|
||||
-------------------------------------------------
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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))
|
||||
@ -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
|
||||
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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 ") },
|
||||
ARGPARSE_group (301, N_("@\nOptions:\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\""},
|
||||
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"),
|
||||
|
||||
{ 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, "@"},
|
||||
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", "@"),
|
||||
|
||||
{0}
|
||||
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)
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
277
common/get-passphrase.c
Normal file
277
common/get-passphrase.c
Normal 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
47
common/get-passphrase.h
Normal 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*/
|
@ -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;
|
||||
}
|
||||
|
155
common/percent.c
155
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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 --*/
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
33
g10/misc.c
33
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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
12
sm/export.c
12
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);
|
||||
}
|
||||
|
||||
|
12
sm/import.c
12
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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user