Preparing for a release
authorWerner Koch <wk@gnupg.org>
Sat, 6 Mar 2004 20:11:19 +0000 (20:11 +0000)
committerWerner Koch <wk@gnupg.org>
Sat, 6 Mar 2004 20:11:19 +0000 (20:11 +0000)
15 files changed:
ChangeLog
NEWS
common/ChangeLog
common/Makefile.am
common/asshelp.c [new file with mode: 0644]
common/asshelp.h [new file with mode: 0644]
configure.ac
m4/ChangeLog
m4/libgcrypt.m4
sm/ChangeLog
sm/call-agent.c
sm/call-dirmngr.c
sm/certchain.c
sm/certdump.c
sm/gpgsm.h

index 5fbf045..a709717 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2004-03-06  Werner Koch  <wk@gnupg.org>
+
+       Released 1.9.6.
+       
+       * configure.ac: Check the Libgcrypt API.
+
 2004-02-25  Werner Koch  <wk@gnupg.org>
 
        * configure.ac: New option --disable-threads to inhibit
diff --git a/NEWS b/NEWS
index 905c585..934bce7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
-Noteworthy changes in version 1.9.6
+Noteworthy changes in version 1.9.6 (2004-03-06)
 ------------------------------------------------
 
+ * Code cleanups and bug fixes.
 
 
 Noteworthy changes in version 1.9.5 (2004-02-21)
index 6f02303..4889db4 100644 (file)
@@ -1,3 +1,8 @@
+2004-03-03  Werner Koch  <wk@gnupg.org>
+
+       * asshelp.c, asshelp.h: New.
+       (send_pinentry_environment): New. Code taken from ../sm/call-agent.c.
+
 2004-02-19  Werner Koch  <wk@gnupg.org>
 
        * simple-pwquery.c (agent_open): Don't mangle INFOSTR.
index a5d2a4e..4e7fd50 100644 (file)
@@ -39,6 +39,7 @@ libcommon_a_SOURCES = \
        membuf.c membuf.h \
        iobuf.c iobuf.h \
        ttyio.c ttyio.h \
+       asshelp.c asshelp.h \
        signal.c \
        dynload.h
 
@@ -46,7 +47,7 @@ libcommon_a_SOURCES = \
 libcommon_a_LIBADD = @LIBOBJS@
 
 libsimple_pwquery_a_SOURCES = \
-       simple-pwquery.c simple-pwquery.h
+       simple-pwquery.c simple-pwquery.h asshelp.c asshelp.h
 
 libsimple_pwquery_a_LIBADD = @LIBOBJS@
 
diff --git a/common/asshelp.c b/common/asshelp.c
new file mode 100644 (file)
index 0000000..23feca5
--- /dev/null
@@ -0,0 +1,166 @@
+/* asshelp.c - Helper functions for Assuan
+ * Copyright (C) 2002, 2004 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#include "util.h"
+
+#include "asshelp.h"
+
+/* Send the assuan command pertaining to the pinenry environment.  The
+   OPT_* arguments are optional and may be used to overide the
+   defaults taken from the current locale. */
+gpg_error_t
+send_pinentry_environment (assuan_context_t ctx,
+                           const char *opt_display,
+                           const char *opt_ttyname,
+                           const char *opt_ttytype,
+                           const char *opt_lc_ctype,
+                           const char *opt_lc_messages)
+{
+  int rc = 0;
+  char *dft_display = NULL;
+  char *dft_ttyname = NULL;
+  char *dft_ttytype = NULL;
+  char *old_lc = NULL; 
+  char *dft_lc = NULL;
+
+  dft_display = getenv ("DISPLAY");
+  if (opt_display || dft_display)
+    {
+      char *optstr;
+      if (asprintf (&optstr, "OPTION display=%s",
+                   opt_display ? opt_display : dft_display) < 0)
+       return gpg_error_from_errno (errno);
+      rc = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL,
+                           NULL);
+      free (optstr);
+      if (rc)
+       return map_assuan_err (rc);
+    }
+  if (!opt_ttyname)
+    {
+      dft_ttyname = getenv ("GPG_TTY");
+      if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
+        dft_ttyname = ttyname (0);
+    }
+  if (opt_ttyname || dft_ttyname)
+    {
+      char *optstr;
+      if (asprintf (&optstr, "OPTION ttyname=%s",
+                   opt_ttyname ? opt_ttyname : dft_ttyname) < 0)
+       return gpg_error_from_errno (errno);
+      rc = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL,
+                           NULL);
+      free (optstr);
+      if (rc)
+       return map_assuan_err (rc);
+    }
+  dft_ttytype = getenv ("TERM");
+  if (opt_ttytype || (dft_ttyname && dft_ttytype))
+    {
+      char *optstr;
+      if (asprintf (&optstr, "OPTION ttytype=%s",
+                   opt_ttyname ? opt_ttytype : dft_ttytype) < 0)
+       return gpg_error_from_errno (errno);
+      rc = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL,
+                           NULL);
+      free (optstr);
+      if (rc)
+       return map_assuan_err (rc);
+    }
+#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
+  old_lc = setlocale (LC_CTYPE, NULL);
+  if (old_lc)
+    {
+      old_lc = strdup (old_lc);
+      if (!old_lc)
+        return gpg_error_from_errno (errno);
+    }
+  dft_lc = setlocale (LC_CTYPE, "");
+#endif
+  if (opt_lc_ctype || (dft_ttyname && dft_lc))
+    {
+      char *optstr;
+      if (asprintf (&optstr, "OPTION lc-ctype=%s",
+                   opt_lc_ctype ? opt_lc_ctype : dft_lc) < 0)
+       rc = gpg_error_from_errno (errno);
+      else
+       {
+         rc = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL,
+                               NULL);
+         free (optstr);
+         if (rc)
+           rc = map_assuan_err (rc);
+       }
+    }
+#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
+  if (old_lc)
+    {
+      setlocale (LC_CTYPE, old_lc);
+      free (old_lc);
+    }
+#endif
+  if (rc)
+    return rc;
+#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
+  old_lc = setlocale (LC_MESSAGES, NULL);
+  if (old_lc)
+    {
+      old_lc = strdup (old_lc);
+      if (!old_lc)
+        return gpg_error_from_errno (errno);
+    }
+  dft_lc = setlocale (LC_MESSAGES, "");
+#endif
+  if (opt_lc_messages || (dft_ttyname && dft_lc))
+    {
+      char *optstr;
+      if (asprintf (&optstr, "OPTION lc-messages=%s",
+                   opt_lc_messages ? opt_lc_messages : dft_lc) < 0)
+       rc = gpg_error_from_errno (errno);
+      else
+       {
+         rc = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL,
+                               NULL);
+         free (optstr);
+         if (rc)
+           rc = map_assuan_err (rc);
+       }
+    }
+#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
+  if (old_lc)
+    {
+      setlocale (LC_MESSAGES, old_lc);
+      free (old_lc);
+    }
+#endif
+
+  return rc;
+}
+
diff --git a/common/asshelp.h b/common/asshelp.h
new file mode 100644 (file)
index 0000000..9935948
--- /dev/null
@@ -0,0 +1,36 @@
+/* asshelp.h - Helper functions for Assuan
+ *     Copyright (C) 2004 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef GNUPG_COMMON_ASSHELP_H
+#define GNUPG_COMMON_ASSHELP_H
+
+#include <assuan.h>
+#include <gpg-error.h>
+
+gpg_error_t
+send_pinentry_environment (assuan_context_t ctx,
+                           const char *opt_display,
+                           const char *opt_ttyname,
+                           const char *opt_ttytype,
+                           const char *opt_lc_ctype,
+                           const char *opt_lc_messages);
+
+
+#endif /*GNUPG_COMMON_ASSHELP_H*/
index aed97fd..a8e84dc 100644 (file)
@@ -24,18 +24,24 @@ min_automake_version="1.7.6"
 
 # Version number: Remember to change it immediately *after* a release.
 #                 Add a "-cvs" prefix for non-released code.
-AC_INIT(gnupg, 1.9.6-cvs, gnupg-devel@gnupg.org)
+AC_INIT(gnupg, 1.9.6, gnupg-devel@gnupg.org)
 # Set development_version to yes if the minor number is odd or you
 # feel that the default check for a development version is not
 # sufficient.
 development_version=yes
 NEED_GPG_ERROR_VERSION=0.6
-NEED_LIBGCRYPT_VERSION=1.1.92
+
+NEED_LIBGCRYPT_API=1
+NEED_LIBGCRYPT_VERSION=1.1.93
+
 NEED_LIBASSUAN_VERSION=0.6.4
+
 NEED_KSBA_VERSION=0.9.4
+
 NEED_OPENSC_VERSION=0.8.0
 
 
+
 PACKAGE=$PACKAGE_NAME
 VERSION=$PACKAGE_VERSION
 
@@ -411,7 +417,7 @@ AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION",
 #
 # Libgcrypt is our generic crypto library
 #
-AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_VERSION",
+AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION",
         have_libgcrypt=yes,have_libgcrypt=no)
 
 
@@ -1022,7 +1028,7 @@ if test "$have_libgcrypt" = "no"; then
 *** You need libgcrypt to build this program.
 **  This library is for example available at
 ***   ftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/
-*** (at least version $NEED_LIBGCRYPT_VERSION is required.)
+*** (at least version $NEED_LIBGCRYPT_VERSION using API $NEED_LIBGCRYPT_API) is required.)
 ***]])
 fi
 if test "$have_libassuan" = "no"; then
index d6ac513..efcded7 100644 (file)
@@ -1,3 +1,7 @@
+2004-03-06  Werner Koch  <wk@gnupg.org>
+
+       * libgcrypt.m4: Updated.
+
 2004-02-18  Werner Koch  <wk@gnupg.org>
 
        * gpg-error.m4, libgcrypt.m4, libassuan.m4, ksba.m4: New.
index 0e8ab58..e5f2a43 100644 (file)
@@ -1,5 +1,5 @@
 dnl Autoconf macros for libgcrypt
-dnl       Copyright (C) 2002 Free Software Foundation, Inc.
+dnl       Copyright (C) 2002, 2004 Free Software Foundation, Inc.
 dnl
 dnl This file is free software; as a special exception the author gives
 dnl unlimited permission to copy and/or distribute it, with or without
@@ -12,7 +12,13 @@ dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION,
 dnl                   [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
-dnl Test for liblibgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS
+dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS.
+dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed
+dnl with the API version to also check the API compatibility. Example:
+dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed 
+dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1.  Using
+dnl this features allows to prevent build against newer versions of libgcrypt
+dnl with a changed API.
 dnl
 AC_DEFUN(AM_PATH_LIBGCRYPT,
 [ AC_ARG_WITH(libgcrypt-prefix,
@@ -26,7 +32,15 @@ AC_DEFUN(AM_PATH_LIBGCRYPT,
   fi
 
   AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no)
-  min_libgcrypt_version=ifelse([$1], ,0.4.4,$1)
+  tmp=ifelse([$1], ,1:1.2.0,$1)
+  if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
+     req_libgcrypt_api=`echo "$tmp"     | sed 's/\(.*\):\(.*\)/\1/'`
+     min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'`
+  else
+     req_libgcrypt_api=0
+     min_libgcrypt_version="$tmp"
+  fi
+
   AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version)
   ok=no
   if test "$LIBGCRYPT_CONFIG" != "no" ; then
@@ -36,7 +50,7 @@ AC_DEFUN(AM_PATH_LIBGCRYPT,
                sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
     req_micro=`echo $min_libgcrypt_version | \
                sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
-    libgcrypt_config_version=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --version`
+    libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
     major=`echo $libgcrypt_config_version | \
                sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
     minor=`echo $libgcrypt_config_version | \
@@ -60,14 +74,33 @@ AC_DEFUN(AM_PATH_LIBGCRYPT,
     fi
   fi
   if test $ok = yes; then
-    LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --cflags`
-    LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --libs`
     AC_MSG_RESULT(yes)
+  else
+    AC_MSG_RESULT(no)
+  fi
+  if test $ok = yes; then
+     # If we have a recent libgcrypt, we should also check that the
+     # API is compatible
+     if test "$req_libgcrypt_api" -gt 0 ; then
+        tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
+        if test "$tmp" -gt 0 ; then
+           AC_MSG_CHECKING([LIBGCRYPT API version])
+           if test "$req_libgcrypt_api" -eq "$tmp" ; then
+             AC_MSG_RESULT(okay)
+           else
+             ok=no
+             AC_MSG_RESULT([does not match (want=$req_libgcrypt_api got=$tmp)])
+           fi
+        fi
+     fi
+  fi
+  if test $ok = yes; then
+    LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags`
+    LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs`
     ifelse([$2], , :, [$2])
   else
     LIBGCRYPT_CFLAGS=""
     LIBGCRYPT_LIBS=""
-    AC_MSG_RESULT(no)
     ifelse([$3], , :, [$3])
   fi
   AC_SUBST(LIBGCRYPT_CFLAGS)
index 545f93d..eb1c608 100644 (file)
@@ -1,5 +1,20 @@
+2004-03-04  Werner Koch  <wk@gnupg.org>
+
+       * call-dirmngr.c (gpgsm_dirmngr_isvalid): New arg ISSUER_CERT.
+
+       * certchain.c (is_cert_still_valid): New.  Code moved from ...
+       (gpgsm_validate_chain): ... here because we now need to check at
+       two places and at a later stage, so that we can pass the issuer
+       cert down to the dirmngr.
+
 2004-03-03  Werner Koch  <wk@gnupg.org>
 
+       * call-agent.c (start_agent): Replaced pinentry setup code by a
+       call to a new common function.
+
+       * certdump.c (gpgsm_format_keydesc): Make sure the string is
+       returned as utf-8.
+
        * export.c (gpgsm_export): Make sure that we don't export more
        than one certificate.
 
index 053959b..15ae5ea 100644 (file)
@@ -34,6 +34,7 @@
 #include <gcrypt.h>
 #include <assuan.h>
 #include "i18n.h"
+#include "asshelp.h"
 #include "keydb.h" /* fixme: Move this to import.c */
 #include "../common/membuf.h"
 
@@ -68,12 +69,7 @@ start_agent (void)
 {
   int rc = 0;
   char *infostr, *p;
-  ASSUAN_CONTEXT ctx;
-  char *dft_display = NULL;
-  char *dft_ttyname = NULL;
-  char *dft_ttytype = NULL;
-  char *old_lc = NULL;
-  char *dft_lc = NULL;
+  assuan_context_t ctx;
 
   if (agent_ctx)
     return 0; /* fixme: We need a context for each thread or serialize
@@ -170,118 +166,9 @@ start_agent (void)
   if (rc)
     return map_assuan_err (rc);
 
-  dft_display = getenv ("DISPLAY");
-  if (opt.display || dft_display)
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION display=%s",
-                   opt.display ? opt.display : dft_display) < 0)
-       return OUT_OF_CORE (errno);
-      rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                           NULL);
-      free (optstr);
-      if (rc)
-       return map_assuan_err (rc);
-    }
-  if (!opt.ttyname)
-    {
-      dft_ttyname = getenv ("GPG_TTY");
-      if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
-        dft_ttyname = ttyname (0);
-    }
-  if (opt.ttyname || dft_ttyname)
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION ttyname=%s",
-                   opt.ttyname ? opt.ttyname : dft_ttyname) < 0)
-       return OUT_OF_CORE (errno);
-      rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                           NULL);
-      free (optstr);
-      if (rc)
-       return map_assuan_err (rc);
-    }
-  dft_ttytype = getenv ("TERM");
-  if (opt.ttytype || (dft_ttyname && dft_ttytype))
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION ttytype=%s",
-                   opt.ttyname ? opt.ttytype : dft_ttytype) < 0)
-       return OUT_OF_CORE (errno);
-      rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                           NULL);
-      free (optstr);
-      if (rc)
-       return map_assuan_err (rc);
-    }
-#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
-  old_lc = setlocale (LC_CTYPE, NULL);
-  if (old_lc)
-    {
-      old_lc = strdup (old_lc);
-      if (!old_lc)
-        return OUT_OF_CORE (errno);
-    }
-  dft_lc = setlocale (LC_CTYPE, "");
-#endif
-  if (opt.lc_ctype || (dft_ttyname && dft_lc))
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION lc-ctype=%s",
-                   opt.lc_ctype ? opt.lc_ctype : dft_lc) < 0)
-       rc = OUT_OF_CORE (errno);
-      else
-       {
-         rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                               NULL);
-         free (optstr);
-         if (rc)
-           rc = map_assuan_err (rc);
-       }
-    }
-#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
-  if (old_lc)
-    {
-      setlocale (LC_CTYPE, old_lc);
-      free (old_lc);
-    }
-#endif
-  if (rc)
-    return rc;
-#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
-  old_lc = setlocale (LC_MESSAGES, NULL);
-  if (old_lc)
-    {
-      old_lc = strdup (old_lc);
-      if (!old_lc)
-        return OUT_OF_CORE (errno);
-    }
-  dft_lc = setlocale (LC_MESSAGES, "");
-#endif
-  if (opt.lc_messages || (dft_ttyname && dft_lc))
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION lc-messages=%s",
-                   opt.lc_messages ? opt.lc_messages : dft_lc) < 0)
-       rc = OUT_OF_CORE (errno);
-      else
-       {
-         rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                               NULL);
-         free (optstr);
-         if (rc)
-           rc = map_assuan_err (rc);
-       }
-    }
-#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
-  if (old_lc)
-    {
-      setlocale (LC_MESSAGES, old_lc);
-      free (old_lc);
-    }
-#endif
-
-  return rc;
+  return send_pinentry_environment (agent_ctx,
+                                    opt.display, opt.ttyname, opt.ttytype,
+                                    opt.lc_ctype, opt.lc_messages);
 }
 
 
index ba96df4..4f07fec 100644 (file)
@@ -49,6 +49,7 @@ static int force_pipe_server = 0;
 struct inq_certificate_parm_s {
   ASSUAN_CONTEXT ctx;
   ksba_cert_t cert;
+  ksba_cert_t issuer_cert;
 };
 
 struct lookup_parm_s {
@@ -239,27 +240,45 @@ inq_certificate (void *opaque, const char *line)
   AssuanError rc;
   const unsigned char *der;
   size_t derlen;
+  int issuer_mode = 0;
 
-  if (!(!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8])))
+  if (!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]))
+    {
+      line += 8;
+    }
+  else if (!strncmp (line, "SENDISSUERCERT", 14)
+           && (line[14] == ' ' || !line[14]))
+    {
+      line += 14;
+      issuer_mode = 1;
+    }
+  else
     {
       log_error ("unsupported inquiry `%s'\n", line);
       return ASSUAN_Inquire_Unknown;
     }
-  line += 8;
 
   if (!*line)
-    { /* send the current certificate */
-      der = ksba_cert_get_image (parm->cert, &derlen);
+    { /* Send the current certificate. */
+      der = ksba_cert_get_image (issuer_mode? parm->issuer_cert : parm->cert,
+                                 &derlen);
       if (!der)
         rc = ASSUAN_Inquire_Error;
       else
         rc = assuan_send_data (parm->ctx, der, derlen);
     }
+  else if (issuer_mode)
+    {
+      log_error ("sending specific issuer certificate back "
+                 "is not yet implemented\n");
+      rc = ASSUAN_Inquire_Error;
+    }
   else 
-    { /* send the given certificate */
+    { /* Send the given certificate. */
       int err;
       ksba_cert_t cert;
 
+
       err = gpgsm_find_cert (line, &cert);
       if (err)
         {
@@ -293,7 +312,7 @@ inq_certificate (void *opaque, const char *line)
   request first.
  */
 int
-gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp)
+gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
 {
   int rc;
   char *certid;
@@ -328,6 +347,7 @@ gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp)
 
   parm.ctx = dirmngr_ctx;
   parm.cert = cert;
+  parm.issuer_cert = issuer_cert;
 
   /* FIXME: If --disable-crl-checks has been set, we should pass an
      option to dirmngr, so that no fallback CRL check is done after an
index bb3fd03..2904680 100644 (file)
@@ -347,7 +347,7 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
       
       if (opt.verbose)
         log_info (_("looking up issuer at external location\n"));
-      /* dirmngr is confused about unknown attributes so has a quick
+      /* dirmngr is confused about unknown attributes so as a quick
          and ugly hack we locate the CN and use this and the
          following.  Fixme: we should have far better parsing in the
          dirmngr. */
@@ -469,6 +469,55 @@ gpgsm_is_root_cert (ksba_cert_t cert)
   return yes;
 }
 
+
+/* This is a helper for gpgsm_validate_chain. */
+static gpg_error_t 
+is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp,
+                     ksba_cert_t subject_cert, ksba_cert_t issuer_cert,
+                     int *any_revoked, int *any_no_crl, int *any_crl_too_old)
+{
+  if (!opt.no_crl_check || ctrl->use_ocsp)
+    {
+      gpg_error_t err;
+
+      err = gpgsm_dirmngr_isvalid (subject_cert, ctrl->use_ocsp);
+      if (err)
+        {
+          /* Fixme: We should change the wording because we may
+             have used OCSP. */
+          switch (gpg_err_code (err))
+            {
+            case GPG_ERR_CERT_REVOKED:
+              do_list (1, lm, fp, _("certificate has been revoked"));
+              *any_revoked = 1;
+              /* Store that in the keybox so that key listings are
+                 able to return the revoked flag.  We don't care
+                 about error, though. */
+              keydb_set_cert_flags (subject_cert, KEYBOX_FLAG_VALIDITY, 0,
+                                    VALIDITY_REVOKED);
+              break;
+            case GPG_ERR_NO_CRL_KNOWN:
+              do_list (1, lm, fp, _("no CRL found for certificate"));
+              *any_no_crl = 1;
+              break;
+            case GPG_ERR_CRL_TOO_OLD:
+              do_list (1, lm, fp, _("the available CRL is too old"));
+              if (!lm)
+                log_info (_("please make sure that the "
+                            "\"dirmngr\" is properly installed\n"));
+              *any_crl_too_old = 1;
+              break;
+            default:
+              do_list (1, lm, fp, _("checking the CRL failed: %s"),
+                       gpg_strerror (rc));
+              return err;
+            }
+        }
+    }
+  return 0;
+}
+
+
 \f
 /* Validate a chain and optionally return the nearest expiration time
    in R_EXPTIME. With LISTMODE set to 1 a special listmode is
@@ -597,46 +646,10 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
             goto leave;
         }
 
-      if (!opt.no_crl_check || ctrl->use_ocsp)
-        {
-          rc = gpgsm_dirmngr_isvalid (subject_cert, ctrl->use_ocsp);
-          if (rc)
-            {
-              /* Fixme: We should change the wording because we may
-                 have used OCSP. */
-              switch (gpg_err_code (rc))
-                {
-                case GPG_ERR_CERT_REVOKED:
-                  do_list (1, lm, fp, _("certificate has been revoked"));
-                  any_revoked = 1;
-                  /* Store that in the keybox so that key listings are
-                     able to return the revoked flag.  We don't care
-                     about error, though. */
-                  keydb_set_cert_flags (subject_cert, KEYBOX_FLAG_VALIDITY, 0,
-                                        VALIDITY_REVOKED);
-                  break;
-                case GPG_ERR_NO_CRL_KNOWN:
-                  do_list (1, lm, fp, _("no CRL found for certificate"));
-                  any_no_crl = 1;
-                  break;
-                case GPG_ERR_CRL_TOO_OLD:
-                  do_list (1, lm, fp, _("the available CRL is too old"));
-                  if (!lm)
-                    log_info (_("please make sure that the "
-                                "\"dirmngr\" is properly installed\n"));
-                  any_crl_too_old = 1;
-                  break;
-                default:
-                  do_list (1, lm, fp, _("checking the CRL failed: %s"),
-                           gpg_strerror (rc));
-                  goto leave;
-                }
-              rc = 0;
-            }
-        }
 
+      /* Is this a self-signed certificate? */
       if (subject && !strcmp (issuer, subject))
-        {
+        {  /* Yes. */
           if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
             {
               do_list (1, lm, fp,
@@ -684,7 +697,15 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
                          gpg_strerror (rc));
             }
           
-          break;  /* okay, a self-signed certicate is an end-point */
+          /* Check for revocations etc. */
+          rc = is_cert_still_valid (ctrl, lm, fp,
+                                    subject_cert, subject_cert,
+                                    &any_revoked, &any_no_crl,
+                                    &any_crl_too_old);
+          if (rc)
+            goto leave;
+
+          break;  /* Okay: a self-signed certicate is an end-point. */
         }
       
       depth++;
@@ -801,6 +822,14 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
             }
         }
 
+      /* Check for revocations etc. */
+      rc = is_cert_still_valid (ctrl, lm, fp,
+                                subject_cert, issuer_cert,
+                                &any_revoked, &any_no_crl, &any_crl_too_old);
+      if (rc)
+        goto leave;
+
+
       if (opt.verbose && !listmode)
         log_info ("certificate is good\n");
       
index f2c21f7..30cd0bd 100644 (file)
 #include <unistd.h> 
 #include <time.h>
 #include <assert.h>
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#ifdef HAVE_LANGINFO_CODESET
+#include <langinfo.h>
+#endif
 
 #include "gpgsm.h"
 #include <gcrypt.h>
@@ -601,12 +607,14 @@ gpgsm_format_name (const char *name)
 char *
 gpgsm_format_keydesc (ksba_cert_t cert)
 {
+  int rc;
   char *name, *subject, *buffer, *p;
   const char *s;
   ksba_isotime_t t;
   char created[20];
   char *sn;
   ksba_sexp_t sexp;
+  char *orig_codeset = NULL;
 
   name = ksba_cert_get_subject (cert, 0);
   subject = name? gpgsm_format_name (name) : NULL;
@@ -622,7 +630,24 @@ gpgsm_format_keydesc (ksba_cert_t cert)
   else
     *created = 0;
 
-  if ( asprintf (&name,
+
+#ifdef ENABLE_NLS
+  /* The Assuan agent protol requires us to transmit utf-8 strings */
+  orig_codeset = bind_textdomain_codeset (PACKAGE, NULL);
+#ifdef HAVE_LANGINFO_CODESET
+  if (!orig_codeset)
+    orig_codeset = nl_langinfo (CODESET);
+#endif
+  if (orig_codeset)
+    { /* We only switch when we are able to restore the codeset later. */
+      orig_codeset = xstrdup (orig_codeset);
+      if (!bind_textdomain_codeset (PACKAGE, "utf-8"))
+        orig_codeset = NULL; 
+    }
+#endif
+
+
+  rc = asprintf (&name,
                  _("Please enter the passphrase to unlock the"
                    " secret key for:\n"
                    "\"%s\"\n"
@@ -630,7 +655,15 @@ gpgsm_format_keydesc (ksba_cert_t cert)
                  subject? subject:"?",
                  sn? sn: "?",
                  gpgsm_get_short_fingerprint (cert),
-                 created) < 0)
+                 created);
+
+#ifdef ENABLE_NLS
+  if (orig_codeset)
+    bind_textdomain_codeset (PACKAGE, orig_codeset);
+#endif
+  xfree (orig_codeset);
+
+  if (rc < 0)
     {
       int save_errno = errno;
       xfree (subject);
index c0434d7..62bc053 100644 (file)
@@ -288,7 +288,8 @@ int gpgsm_agent_learn (void);
 int gpgsm_agent_passwd (const char *hexkeygrip, const char *desc);
 
 /*-- call-dirmngr.c --*/
-int gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp);
+int gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert,
+                           int use_ocsp);
 int gpgsm_dirmngr_lookup (ctrl_t ctrl, STRLIST names,
                           void (*cb)(void*, ksba_cert_t), void *cb_value);
 int gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,