From 530a0a91c4f5dc935278f64be26090f51acc9586 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 29 Sep 2004 13:50:31 +0000 Subject: [PATCH] * minip12.c (parse_bag_encrypted_data): Print error if a bad passphrase has been given. * gpg-agent.texi (Invoking GPG-AGENT): Add a few words about the expected pinentry filename. * import.c (parse_p12): Write an error status line for bad passphrases. Add new arg CTRL and changed caller. * export.c (export_p12): Likewise. --- TODO | 3 ++- agent/ChangeLog | 5 +++++ agent/minip12.c | 27 +++++++++++++++++++++------ agent/protect-tool.c | 2 ++ doc/ChangeLog | 3 +++ doc/gpg-agent.texi | 8 ++++++++ sm/ChangeLog | 6 ++++++ sm/export.c | 33 +++++++++++++++++++++++++++++---- sm/import.c | 32 ++++++++++++++++++++++++++------ 9 files changed, 102 insertions(+), 17 deletions(-) diff --git a/TODO b/TODO index dd69544e1..89db14aad 100644 --- a/TODO +++ b/TODO @@ -86,7 +86,8 @@ might want to have an agent context for each service request * doc/ ** Explain how to setup a root CA key as trusted ** Explain how trustlist.txt might be managed. - +** Document watchgnupg +** Write a script to generate man pages from texi. * Requirements by the BSI ** Support authorityKeyIdentifier.keyIdentifier diff --git a/agent/ChangeLog b/agent/ChangeLog index 22846f3bd..f72bd50c9 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2004-09-29 Werner Koch + + * minip12.c (parse_bag_encrypted_data): Print error if a bad + passphrase has been given. + 2004-09-28 Werner Koch * protect.c (agent_unprotect): Fixed wiping of CLEARTEXT. Thanks diff --git a/agent/minip12.c b/agent/minip12.c index e32a40de2..fc9b26dd1 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -379,7 +379,6 @@ crypt_block (unsigned char *buffer, size_t length, char *salt, int iter, - static int parse_bag_encrypted_data (const unsigned char *buffer, size_t length, int startoffset, const char *pw, @@ -393,8 +392,8 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, char salt[8]; unsigned int iter; unsigned char *plain = NULL; - - + int bad_pass = 0; + where = "start"; if (parse_tag (&p, &n, &ti)) goto bailout; @@ -495,12 +494,21 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, where = "outer.outer.seq"; if (parse_tag (&p, &n, &ti)) - goto bailout; + { + bad_pass = 1; + goto bailout; + } if (ti.class || ti.tag != TAG_SEQUENCE) - goto bailout; + { + bad_pass = 1; + goto bailout; + } if (parse_tag (&p, &n, &ti)) - goto bailout; + { + bad_pass = 1; + goto bailout; + } /* Loop over all certificates inside the bab. */ while (n) @@ -611,6 +619,13 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, gcry_free (plain); log_error ("encryptedData error at \"%s\", offset %u\n", where, (p - buffer)+startoffset); + if (bad_pass) + { + /* Note, that the following string might be used by other programs + to check for a bad passphrase; it should therefore not be + translated or changed. */ + log_error ("possibly bad passphrase given\n"); + } return -1; } diff --git a/agent/protect-tool.c b/agent/protect-tool.c index 7cfb760b8..286adde54 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -882,6 +882,8 @@ export_p12_file (const char *fname) release_passphrase (pw); if (rc) { + if (opt_status_msg && gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE ) + log_info ("[PROTECT-TOOL:] bad-passphrase\n"); log_error ("unprotecting key `%s' failed: %s\n", fname, gpg_strerror (rc)); xfree (key); diff --git a/doc/ChangeLog b/doc/ChangeLog index d7015bd85..6373b0339 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,8 @@ 2004-09-29 Werner Koch + * gpg-agent.texi (Invoking GPG-AGENT): Add a few words about the + expected pinentry filename. + Changed license of the manual stuff to GPL. * gnupg.texi (Top): New menu item Helper Tools. diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index ab28eeb7d..2b45a41c1 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -52,9 +52,17 @@ GPG_TTY=`tty` export GPG_TTY @end smallexample +@noindent It is important that this environment variable always reflects the output of the @code{tty} command. +Please make sure that a proper pinentry program has been installed +under the default filename (which is system dependant) or use the +option @code{pinentry-pgm} to specify the full name of that program. +It is often useful to install a symbolic link from the actual used +pinentry (e.g. @file{/usr/bin/pinentry-gtk}) to the expected +one (e.g. @file{/usr/bin/pinentry}). + @c man end @noindent diff --git a/sm/ChangeLog b/sm/ChangeLog index d68759151..2391deb18 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2004-09-29 Werner Koch + + * import.c (parse_p12): Write an error status line for bad + passphrases. Add new arg CTRL and changed caller. + * export.c (export_p12): Likewise. + 2004-09-14 Werner Koch * certchain.c (gpgsm_validate_chain): Give expired certificates a diff --git a/sm/export.c b/sm/export.c index 3f7457502..15ad87b04 100644 --- a/sm/export.c +++ b/sm/export.c @@ -65,7 +65,8 @@ typedef struct duptable_s *duptable_t; static void print_short_info (ksba_cert_t cert, FILE *fp); -static gpg_error_t export_p12 (const unsigned char *certimg, size_t certimglen, +static gpg_error_t export_p12 (ctrl_t ctrl, + const unsigned char *certimg, size_t certimglen, const char *prompt, const char *keygrip, FILE **retfp); @@ -423,7 +424,7 @@ gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp) prompt = gpgsm_format_keydesc (cert); - rc = export_p12 (image, imagelen, prompt, keygrip, &datafp); + rc = export_p12 (ctrl, image, imagelen, prompt, keygrip, &datafp); xfree (prompt); if (rc) goto leave; @@ -587,6 +588,7 @@ popen_protect_tool (const char *pgmname, "--homedir", opt.homedir, "--p12-export", "--prompt", prompt?prompt:"", + "--enable-status-msg", "--", keygrip, NULL); @@ -610,7 +612,7 @@ popen_protect_tool (const char *pgmname, static gpg_error_t -export_p12 (const unsigned char *certimg, size_t certimglen, +export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen, const char *prompt, const char *keygrip, FILE **retfp) { @@ -621,6 +623,7 @@ export_p12 (const unsigned char *certimg, size_t certimglen, FILE *infp = NULL, *outfp = NULL, *fp = NULL; char buffer[1024]; pid_t pid = -1; + int bad_pass = 0; if (!opt.protect_tool_program || !*opt.protect_tool_program) pgmname = GNUPG_DEFAULT_PROTECT_TOOL; @@ -675,7 +678,21 @@ export_p12 (const unsigned char *certimg, size_t certimglen, if (cont_line) log_printf ("%s", buffer); else - log_info ("%s", buffer); + { + if (!strncmp (buffer, "gpg-protect-tool: [PROTECT-TOOL:] ",34)) + { + char *p, *pend; + + p = buffer + 34; + pend = strchr (p, ' '); + if (pend) + *pend = 0; + if ( !strcmp (p, "bad-passphrase")) + bad_pass++; + } + else + log_info ("%s", buffer); + } pos = 0; cont_line = (c != '\n'); } @@ -731,6 +748,14 @@ export_p12 (const unsigned char *certimg, size_t certimglen, } else *retfp = outfp; + if (bad_pass) + { + /* During export this is the passphrase used to unprotect the + key and not the pkcs#12 thing as in export. Therefore we can + issue the regular passphrase status. FIXME: replace the all + zero keyid by a regular one. */ + gpgsm_status (ctrl, STATUS_BAD_PASSPHRASE, "0000000000000000"); + } return err; } diff --git a/sm/import.c b/sm/import.c index 836ac0877..938bc17d0 100644 --- a/sm/import.c +++ b/sm/import.c @@ -55,7 +55,7 @@ struct stats_s { }; -static gpg_error_t parse_p12 (ksba_reader_t reader, FILE **retfp, +static gpg_error_t parse_p12 (ctrl_t ctrl, ksba_reader_t reader, FILE **retfp, struct stats_s *stats); @@ -341,7 +341,7 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) Base64Context b64p12rdr; ksba_reader_t p12rdr; - rc = parse_p12 (reader, &certfp, stats); + rc = parse_p12 (ctrl, reader, &certfp, stats); if (!rc) { any = 1; @@ -572,13 +572,14 @@ popen_protect_tool (const char *pgmname, /* Assume that the reader is at a pkcs#12 message and try to import - certificates from that stupid format. We will alos store secret + certificates from that stupid format. We will also store secret keys. All of the pkcs#12 parsing and key storing is handled by the gpg-protect-tool, we merely have to take care of receiving the certificates. On success RETFP returns a temporary file with certificates. */ static gpg_error_t -parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats) +parse_p12 (ctrl_t ctrl, ksba_reader_t reader, + FILE **retfp, struct stats_s *stats) { const char *pgmname; gpg_error_t err = 0, child_err = 0; @@ -588,6 +589,7 @@ parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats) char buffer[1024]; size_t nread; pid_t pid = -1; + int bad_pass = 0; if (!opt.protect_tool_program || !*opt.protect_tool_program) pgmname = GNUPG_DEFAULT_PROTECT_TOOL; @@ -681,8 +683,13 @@ parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats) else if ( !strcmp (p, "bad-passphrase")) ; } - else - log_info ("%s", buffer); + else + { + log_info ("%s", buffer); + if (!strncmp (buffer, "gpg-protect-tool: " + "possibly bad passphrase given",46)) + bad_pass++; + } } pos = 0; cont_line = (c != '\n'); @@ -698,6 +705,7 @@ parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats) log_info ("%s\n", buffer); } + /* If we found no error in the output of the cild, setup a suitable error code, which will later be reset if the exit status of the child is 0. */ @@ -738,5 +746,17 @@ parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats) } else *retfp = certfp; + + if (bad_pass) + { + /* We only write a plain error code and not direct + BAD_PASSPHRASE because the pkcs12 parser might issue this + message multiple times, BAd_PASSPHRASE in general requires a + keyID and parts of the import might actually succeed so that + IMPORT_PROBLEM is also not appropriate. */ + gpgsm_status_with_err_code (ctrl, STATUS_ERROR, + "import.parsep12", GPG_ERR_BAD_PASSPHRASE); + } + return err; }