diff --git a/common/ChangeLog b/common/ChangeLog index b1390d599..4dd772d7e 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,5 +1,7 @@ 2008-12-05 Werner Koch + * percent.c, t-percent.c: New. + * exechelp.c (gnupg_spawn_process, gnupg_spawn_process_fd) (gnupg_spawn_process_detached) [W32]: Remove debug output. diff --git a/common/Makefile.am b/common/Makefile.am index 5a5d6ba71..d1a2d4822 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -52,6 +52,7 @@ common_sources = \ yesno.c \ b64enc.c b64dec.c \ convert.c \ + percent.c \ miscellaneous.c \ xasprintf.c \ xreadline.c \ @@ -107,13 +108,14 @@ status-codes.h: Makefile mkstrtable.awk exstatus.awk status.h # # Module tests # -module_tests = t-convert t-gettime t-sysutils t-sexputil +module_tests = t-convert t-percent t-gettime t-sysutils t-sexputil module_maint_tests = t-helpfile t-b64 t_common_ldadd = libcommon.a ../jnlib/libjnlib.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) t_convert_LDADD = $(t_common_ldadd) +t_percent_LDADD = $(t_common_ldadd) t_gettime_LDADD = $(t_common_ldadd) t_sysutils_LDADD = $(t_common_ldadd) t_helpfile_LDADD = $(t_common_ldadd) diff --git a/common/percent.c b/common/percent.c new file mode 100644 index 000000000..a0c78ec7b --- /dev/null +++ b/common/percent.c @@ -0,0 +1,76 @@ +/* percent.c - Percent escaping + * Copyright (C) 2008 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 . + */ + +#include +#include +#include +#include + +#include "util.h" + + +/* Create a newly alloced string from STRING with all spaces and + control characters converted to plus signs or %xx sequences. The + function returns the new string or NULL in case of a malloc + failure. + + Note that we also escape the quote character to work around a bug + in the mingw32 runtime which does not correcty handle command line + quoting. We correctly double the quote mark when calling a program + (i.e. gpg-protect-tool), but the pre-main code does not notice the + double quote as an escaped quote. We do this also on POSIX systems + for consistency. */ +char * +percent_plus_escape (const char *string) +{ + char *buffer, *p; + const char *s; + size_t length; + + for (length=1, s=string; *s; s++) + { + if (*s == '+' || *s == '\"' || *s == '%' + || *(const unsigned char *)s < 0x20) + length += 3; + else + length++; + } + + buffer = p = xtrymalloc (length); + if (!buffer) + return NULL; + + for (s=string; *s; s++) + { + if (*s == '+' || *s == '\"' || *s == '%' + || *(const unsigned char *)s < 0x20) + { + snprintf (p, 4, "%%%02X", *(unsigned char *)s); + p += 3; + } + else if (*s == ' ') + *p++ = '+'; + else + *p++ = *s; + } + *p = 0; + + return buffer; + +} diff --git a/common/t-percent.c b/common/t-percent.c new file mode 100644 index 000000000..93d95f78d --- /dev/null +++ b/common/t-percent.c @@ -0,0 +1,97 @@ +/* t-percent.c - Module test for percent.c + * Copyright (C) 2008 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 . + */ + +#include +#include +#include +#include + +#include "util.h" + +#define pass() do { ; } while(0) +#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\ + __FILE__,__LINE__, (a)); \ + exit (1); \ + } while(0) + +static void +test_percent_plus_escape (void) +{ + static struct { + const char *string; + const char *expect; + } tbl[] = { + { + "", + "" + }, { + "a", + "a", + }, { + " ", + "+", + }, { + " ", + "++" + }, { + "+ +", + "%2B+%2B" + }, { + "\" \"", + "%22+%22" + }, { + "%22", + "%2522" + }, { + "%% ", + "%25%25+" + }, { + "\n ABC\t", + "%0A+ABC%09" + }, { NULL, NULL } + }; + char *buf; + int i; + + for (i=0; tbl[i].string; i++) + { + buf = percent_plus_escape (tbl[i].string); + if (!buf) + { + fprintf (stderr, "out of core: %s\n", strerror (errno)); + exit (2); + } + if (strcmp (buf, tbl[i].expect)) + fail (i); + xfree (buf); + } +} + + +int +main (int argc, char **argv) +{ + (void)argc; + (void)argv; + + test_percent_plus_escape (); + + return 0; +} + diff --git a/common/util.h b/common/util.h index 29955a494..66569e27e 100644 --- a/common/util.h +++ b/common/util.h @@ -199,6 +199,9 @@ const char *hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen); char *hex2str_alloc (const char *hexstring, size_t *r_count); +/*-- percent.c --*/ +char *percent_plus_escape (const char *string); + /*-- homedir.c --*/ const char *standard_homedir (void); diff --git a/g10/ChangeLog b/g10/ChangeLog index eec3d6f0b..0ad19abaf 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,9 @@ +2008-12-05 Werner Koch + + * call-agent.c (percent_plus_escape): Rename to + my_percent_plus_escape and also escape the percent character. + Change all callers. + 2008-11-18 Werner Koch * gpg.c (build_lib_list): Remove. diff --git a/g10/call-agent.c b/g10/call-agent.c index 15c17b038..33025ef27 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -148,15 +148,15 @@ unescape_status_string (const unsigned char *s) escaping. Note that the provided buffer needs to be 3 times the size of ATEXT plus 1. Returns a pointer to the leading Nul in P. */ static char * -percent_plus_escape (char *p, const char *atext) +my_percent_plus_escape (char *p, const char *atext) { const unsigned char *s; for (s=atext; *s; s++) { - if (*s < ' ' || *s == '+') + if (*s < ' ' || *s == '+' || *s == '%') { - sprintf (p, "%%%02X", *s); + snprintf (p, 4, "%%%02X", *s); p += 3; } else if (*s == ' ') @@ -865,25 +865,25 @@ agent_get_passphrase (const char *cache_id, p = stpcpy (line, cmd); if (cache_id && *cache_id) - p = percent_plus_escape (p, cache_id); + p = my_percent_plus_escape (p, cache_id); else *p++ = 'X'; *p++ = ' '; if (err_msg && *err_msg) - p = percent_plus_escape (p, err_msg); + p = my_percent_plus_escape (p, err_msg); else *p++ = 'X'; *p++ = ' '; if (prompt && *prompt) - p = percent_plus_escape (p, prompt); + p = my_percent_plus_escape (p, prompt); else *p++ = 'X'; *p++ = ' '; if (desc_msg && *desc_msg) - p = percent_plus_escape (p, desc_msg); + p = my_percent_plus_escape (p, desc_msg); else *p++ = 'X'; *p = 0; diff --git a/sm/ChangeLog b/sm/ChangeLog index 37ef9e836..67e35f0b5 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,14 @@ +2008-12-05 Werner Koch + + * certreqgen.c (create_request): Provide a custom prompt for the + signing. + + * certdump.c (gpgsm_format_keydesc): Remove debug output. + (gpgsm_format_keydesc): Remove saving of errno as xfree is + supposed not to change it. Use the new percent_plus_escape + function which also fixes the issue that we did not escaped a + percent in the past. + 2008-11-18 Werner Koch * gpgsm.c (make_libversion): New. diff --git a/sm/certdump.c b/sm/certdump.c index ddfc1d120..71907d188 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -924,13 +924,12 @@ gpgsm_fpr_and_name_for_status (ksba_cert_t cert) /* Create a key description for the CERT, this may be passed to the - pinentry. The caller must free the returned string. NULL may be + pinentry. The caller must free the returned string. NULL may be returned on error. */ char * gpgsm_format_keydesc (ksba_cert_t cert) { - char *name, *subject, *buffer, *p; - const char *s; + char *name, *subject, *buffer; ksba_isotime_t t; char created[20]; char expires[20]; @@ -939,10 +938,8 @@ gpgsm_format_keydesc (ksba_cert_t cert) char *orig_codeset; name = ksba_cert_get_subject (cert, 0); - log_printhex ("XXXX NAME: ", name, strlen (name)); subject = name? gpgsm_format_name2 (name, 0) : NULL; ksba_free (name); name = NULL; - log_printhex ("YYYY NAME: ", subject, strlen (subject)); sexp = ksba_cert_get_serial (cert); sn = sexp? gpgsm_format_serial (sexp) : NULL; @@ -975,38 +972,16 @@ gpgsm_format_keydesc (ksba_cert_t cert) if (!name) { - int save_errno = errno; xfree (subject); xfree (sn); - errno = save_errno; return NULL; } xfree (subject); xfree (sn); - buffer = p = xtrymalloc (strlen (name) * 3 + 1); - for (s=name; *s; s++) - { - /* We also escape the quote character to work around a bug in - the mingw32 runtime which does not correcty handle command - line quoting. We correctly double the quote mark when - calling a program (i.e. gpg-protect-tool), but the pre-main - code does not notice the double quote as an escaped - quote. */ - if (*s < ' ' || *s == '+' || *s == '\"') - { - sprintf (p, "%%%02X", *(unsigned char *)s); - p += 3; - } - else if (*s == ' ') - *p++ = '+'; - else - *p++ = *s; - } - *p = 0; + buffer = percent_plus_escape (name); xfree (name); - return buffer; } diff --git a/sm/certreqgen.c b/sm/certreqgen.c index 30b8179fd..ca791aab8 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -788,6 +788,8 @@ create_request (ctrl_t ctrl, gcry_sexp_release (s_pkey); bin2hex (grip, 20, hexgrip); + log_info ("about to sign CSR for key: &%s\n", hexgrip); + if (carddirect) rc = gpgsm_scd_pksign (ctrl, carddirect, NULL, gcry_md_read(md, GCRY_MD_SHA1), @@ -795,11 +797,23 @@ create_request (ctrl_t ctrl, GCRY_MD_SHA1, &sigval, &siglen); else - rc = gpgsm_agent_pksign (ctrl, hexgrip, NULL, - gcry_md_read(md, GCRY_MD_SHA1), - gcry_md_get_algo_dlen (GCRY_MD_SHA1), - GCRY_MD_SHA1, - &sigval, &siglen); + { + char *orig_codeset; + char *desc; + + orig_codeset = i18n_switchto_utf8 (); + desc = percent_plus_escape + (_("To complete this certificate request please enter" + " the passphrase for the key you just created once" + " more.\n")); + i18n_switchback (orig_codeset); + rc = gpgsm_agent_pksign (ctrl, hexgrip, desc, + gcry_md_read(md, GCRY_MD_SHA1), + gcry_md_get_algo_dlen (GCRY_MD_SHA1), + GCRY_MD_SHA1, + &sigval, &siglen); + xfree (desc); + } if (rc) { log_error ("signing failed: %s\n", gpg_strerror (rc)); @@ -818,7 +832,7 @@ create_request (ctrl_t ctrl, } } while (stopreason != KSBA_SR_READY); - + leave: gcry_md_close (md);