dirmngr: Start dirmngr on demand.
[gnupg.git] / dirmngr / crlcache.c
index e087419..13d8a26 100644 (file)
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-/* 
+/*
 
    1. To keep track of the CRLs actually cached and to store the meta
       information of the CRLs a simple record oriented text file is
       used.  Fields in the file are colon (':') separated and values
       containing colons or linefeeds are percent escaped (e.g. a colon
-      itself is represented as "%3A"). 
+      itself is represented as "%3A").
 
       The first field is a record type identifier, so that the file is
-      useful to keep track of other meta data too.  
+      useful to keep track of other meta data too.
 
       The name of the file is "DIR.txt".
 
@@ -53,9 +53,9 @@
                  A "c" or "u" indicate a valid cache entry, however
                  "u" requires that a user root certificate check needs
                  to be done.
-                 An "i" indicates an invalid Cache entry which should
+                 An "i" indicates an invalid cache entry which should
                  not be used but still exists so that it can be
-                 updated at NEXT_UPDATE. 
+                 updated at NEXT_UPDATE.
         Field 2: Hexadecimal encoded SHA-1 hash of the issuer DN using
                  uppercase letters.
         Field 3: Issuer DN in RFC-2253 notation.
@@ -75,7 +75,7 @@
 
       n  bytes  Serialnumber (binary) used as key
                 thus there is no need to store the length explicitly with DB2.
-      1  byte   Reason for revocation 
+      1  byte   Reason for revocation
                 (currently the KSBA reason flags are used)
       15 bytes  ISO date of revocation (e.g. 19980815T142000)
                 Note that there is no terminating 0 stored.
@@ -83,7 +83,7 @@
       The filename used is the hexadecimal (using uppercase letters)
       SHA-1 hash value of the issuer DN prefixed with a "crl-" and
       suffixed with a ".db".  Thus the length of the filename is 47.
-      
+
 
 */
 
 #include "crlfetch.h"
 #include "misc.h"
 #include "cdb.h"
-#include "estream-printf.h"
 
 /* Change this whenever the format changes */
 #define DBDIR_D (opt.system_daemon? "crls.d" : "dirmngr-cache.d")
@@ -133,7 +132,7 @@ static const char oidstr_authorityKeyIdentifier[] = "2.5.29.35";
 
 
 /* Definition of one cached item. */
-struct crl_cache_entry_s 
+struct crl_cache_entry_s
 {
   struct crl_cache_entry_s *next;
   int deleted;        /* True if marked for deletion. */
@@ -164,7 +163,7 @@ struct crl_cache_entry_s
 
 
 /* Definition of the entire cache object. */
-struct crl_cache_s 
+struct crl_cache_s
 {
   crl_cache_entry_t entries;
 };
@@ -178,7 +177,7 @@ static crl_cache_entry_t find_entry (crl_cache_entry_t first,
 
 
 
-/* The currently loaded cache object.  This isi usually initialized
+/* The currently loaded cache object.  This is usually initialized
    right at startup.  */
 static crl_cache_t current_cache;
 
@@ -197,7 +196,7 @@ get_current_cache (void)
 }
 
 
-/* 
+/*
    Create ae directory if it does not yet exists.  Returns on
    success, or -1 on error.
  */
@@ -211,17 +210,17 @@ create_directory_if_needed (const char *name)
   dir = opendir (fname);
   if (!dir)
     {
-      log_info (_("creating directory `%s'\n"), fname);
+      log_info (_("creating directory '%s'\n"), fname);
       if (mkdir (fname, S_IRUSR|S_IWUSR|S_IXUSR) )
         {
           int save_errno = errno;
-          log_error (_("error creating directory `%s': %s\n"),
+          log_error (_("error creating directory '%s': %s\n"),
                      fname, strerror (errno));
           xfree (fname);
           gpg_err_set_errno (save_errno);
           return -1;
         }
-    } 
+    }
   else
     closedir (dir);
   xfree (fname);
@@ -243,7 +242,7 @@ cleanup_cache_dir (int force)
     { /* Very minor sanity checks. */
       if (!strcmp (dname, "~/") || !strcmp (dname, "/" ))
         {
-          log_error (_("ignoring database dir `%s'\n"), dname);
+          log_error (_("ignoring database dir '%s'\n"), dname);
           xfree (dname);
           return -1;
         }
@@ -252,7 +251,7 @@ cleanup_cache_dir (int force)
   dir = opendir (dname);
   if (!dir)
     {
-      log_error (_("error reading directory `%s': %s\n"),
+      log_error (_("error reading directory '%s': %s\n"),
                  dname, strerror (errno));
       xfree (dname);
       return -1;
@@ -265,7 +264,7 @@ cleanup_cache_dir (int force)
           char *cdbname = make_filename (dname, de->d_name, NULL);
           int okay;
           struct stat sbuf;
-     
+
           if (force)
             okay = 1;
           else
@@ -273,19 +272,19 @@ cleanup_cache_dir (int force)
 
           if (okay)
             {
-              log_info (_("removing cache file `%s'\n"), cdbname);
-              if (unlink (cdbname))
+              log_info (_("removing cache file '%s'\n"), cdbname);
+              if (gnupg_remove (cdbname))
                 {
-                  log_error ("failed to remove `%s': %s\n",
+                  log_error ("failed to remove '%s': %s\n",
                              cdbname, strerror (errno));
                   problem = -1;
                 }
             }
           else
-            log_info (_("not removing file `%s'\n"), cdbname);
+            log_info (_("not removing file '%s'\n"), cdbname);
           xfree (cdbname);
         }
-    }    
+    }
   xfree (dname);
   closedir (dir);
   return problem;
@@ -345,7 +344,7 @@ next_line_from_file (estream_t fp, gpg_error_t *r_err)
   if (c == EOF && !len)
     return NULL;
   p[len] = 0;
-      
+
   if (largebuf)
     tmpbuf = xtryrealloc (largebuf, len+1);
   else
@@ -393,7 +392,7 @@ release_cache (crl_cache_t cache)
     {
       entry2 = entry->next;
       release_one_cache_entry (entry);
-  }
+    }
   cache->entries = NULL;
   xfree (cache);
 }
@@ -409,41 +408,41 @@ open_dir_file (const char *fname)
   fp = es_fopen (fname, "r");
   if (!fp)
     {
-      log_error (_("failed to open cache dir file `%s': %s\n"),
+      log_error (_("failed to open cache dir file '%s': %s\n"),
                  fname, strerror (errno));
 
       /* Make sure that the directory exists, try to create if otherwise. */
-      if (create_directory_if_needed (NULL) 
-          || create_directory_if_needed (DBDIR_D)) 
+      if (create_directory_if_needed (NULL)
+          || create_directory_if_needed (DBDIR_D))
         return NULL;
       fp = es_fopen (fname, "w");
       if (!fp)
         {
-          log_error (_("error creating new cache dir file `%s': %s\n"),
+          log_error (_("error creating new cache dir file '%s': %s\n"),
                      fname, strerror (errno));
           return NULL;
         }
       es_fprintf (fp, "v:%d:\n", DBDIRVERSION);
       if (es_ferror (fp))
         {
-          log_error (_("error writing new cache dir file `%s': %s\n"),
+          log_error (_("error writing new cache dir file '%s': %s\n"),
                      fname, strerror (errno));
           es_fclose (fp);
           return NULL;
         }
       if (es_fclose (fp))
         {
-          log_error (_("error closing new cache dir file `%s': %s\n"),
+          log_error (_("error closing new cache dir file '%s': %s\n"),
                      fname, strerror (errno));
           return NULL;
         }
 
-      log_info (_("new cache dir file `%s' created\n"), fname);
+      log_info (_("new cache dir file '%s' created\n"), fname);
 
       fp = es_fopen (fname, "r");
       if (!fp)
         {
-          log_error (_("failed to re-open cache dir file `%s': %s\n"),
+          log_error (_("failed to re-open cache dir file '%s': %s\n"),
                      fname, strerror (errno));
           return NULL;
         }
@@ -471,7 +470,7 @@ check_dir_version (estream_t *fpadr, const char *fname,
         break;
       else if (*line != '#')
         {
-          log_error (_("first record of `%s' is not the version\n"), fname);
+          log_error (_("first record of '%s' is not the version\n"), fname);
           xfree (line);
           return gpg_error (GPG_ERR_CONFIGURATION);
         }
@@ -480,7 +479,9 @@ check_dir_version (estream_t *fpadr, const char *fname,
   if (lineerr)
     return lineerr;
 
-  if (strtol (line+2, NULL, 10) != DBDIRVERSION)
+  /* The !line catches the case of an empty DIR file.  We handle this
+     the same as a non-matching version.  */
+  if (!line || strtol (line+2, NULL, 10) != DBDIRVERSION)
     {
       if (!created && cleanup_on_mismatch)
         {
@@ -518,7 +519,7 @@ static gpg_error_t
 open_dir (crl_cache_t *r_cache)
 {
   crl_cache_t cache;
-  char *fname; 
+  char *fname;
   char *line = NULL;
   gpg_error_t lineerr = 0;
   estream_t fp;
@@ -527,7 +528,7 @@ open_dir (crl_cache_t *r_cache)
   gpg_error_t err = 0;
   int anyerr = 0;
 
-  cache = xtrycalloc (1, sizeof *cache); 
+  cache = xtrycalloc (1, sizeof *cache);
   if (!cache)
     return gpg_error_from_syserror ();
 
@@ -587,33 +588,39 @@ open_dir (crl_cache_t *r_cache)
                 case 2: entry->issuer_hash = p; break;
                 case 3: entry->issuer = unpercent_string (p); break;
                 case 4: entry->url = unpercent_string (p); break;
-                case 5: strncpy (entry->this_update, p, 15); break;
-                case 6: strncpy (entry->next_update, p, 15); break;
+                case 5:
+                 strncpy (entry->this_update, p, 15);
+                 entry->this_update[15] = 0;
+                 break;
+                case 6:
+                 strncpy (entry->next_update, p, 15);
+                 entry->next_update[15] = 0;
+                 break;
                 case 7: entry->dbfile_hash = p; break;
                 case 8: if (*p) entry->crl_number = p; break;
-                case 9: 
+                case 9:
                   if (*p)
                     entry->authority_issuer = unpercent_string (p);
                   break;
-                case 10: 
+                case 10:
                   if (*p)
                     entry->authority_serialno = unpercent_string (p);
                   break;
-                case 11: 
+                case 11:
                   if (*p)
                     entry->check_trust_anchor = xtrystrdup (p);
                   break;
                 default:
                   if (*p)
                     log_info (_("extra field detected in crl record of "
-                                "`%s' line %u\n"), fname, lineno);
+                                "'%s' line %u\n"), fname, lineno);
                   break;
                 }
             }
 
           if (!entry->issuer_hash)
             {
-              log_info (_("invalid line detected in `%s' line %u\n"),
+              log_info (_("invalid line detected in '%s' line %u\n"),
                         fname, lineno);
               xfree (entry);
               entry = NULL;
@@ -622,14 +629,14 @@ open_dir (crl_cache_t *r_cache)
             {
               /* Fixme: The duplicate checking used is not very
                  effective for large numbers of issuers. */
-              log_info (_("duplicate entry detected in `%s' line %u\n"),
+              log_info (_("duplicate entry detected in '%s' line %u\n"),
                         fname, lineno);
               xfree (entry);
               entry = NULL;
             }
           else
             {
-              line = NULL; 
+              line = NULL;
               *entrytail = entry;
               entrytail = &entry->next;
             }
@@ -637,7 +644,7 @@ open_dir (crl_cache_t *r_cache)
       else if (*line == '#')
         ;
       else
-        log_info (_("unsupported record type in `%s' line %u skipped\n"),
+        log_info (_("unsupported record type in '%s' line %u skipped\n"),
                   fname, lineno);
 
       if (line)
@@ -646,12 +653,12 @@ open_dir (crl_cache_t *r_cache)
   if (lineerr)
     {
       err = lineerr;
-      log_error (_("error reading `%s': %s\n"), fname, gpg_strerror (err));
+      log_error (_("error reading '%s': %s\n"), fname, gpg_strerror (err));
       goto leave;
     }
   if (es_ferror (fp))
     {
-      log_error (_("error reading `%s': %s\n"), fname, strerror (errno));
+      log_error (_("error reading '%s': %s\n"), fname, strerror (errno));
       err = gpg_error (GPG_ERR_CONFIGURATION);
       goto leave;
     }
@@ -663,29 +670,29 @@ open_dir (crl_cache_t *r_cache)
       if (strlen (entry->issuer_hash) != 40)
         {
           anyerr++;
-          log_error (_("invalid issuer hash in `%s' line %u\n"),
+          log_error (_("invalid issuer hash in '%s' line %u\n"),
                      fname, entry->lineno);
         }
       else if ( !*entry->issuer )
         {
           anyerr++;
-          log_error (_("no issuer DN in `%s' line %u\n"),
+          log_error (_("no issuer DN in '%s' line %u\n"),
                      fname, entry->lineno);
         }
       else if ( check_isotime (entry->this_update)
                 || check_isotime (entry->next_update))
         {
           anyerr++;
-          log_error (_("invalid timestamp in `%s' line %u\n"),
+          log_error (_("invalid timestamp in '%s' line %u\n"),
                      fname, entry->lineno);
         }
 
       /* Checks not leading to an immediate fail. */
       if (strlen (entry->dbfile_hash) != 32)
-        log_info (_("WARNING: invalid cache file hash in `%s' line %u\n"),
-                  fname, entry->lineno); 
+        log_info (_("WARNING: invalid cache file hash in '%s' line %u\n"),
+                  fname, entry->lineno);
     }
-     
+
   if (anyerr)
     {
       log_error (_("detected errors in cache dir file\n"));
@@ -738,9 +745,9 @@ write_dir_line_crl (estream_t fp, crl_cache_entry_t e)
   es_putc (':', fp);
   write_percented_string (e->url, fp);
   es_putc (':', fp);
-  es_fwrite (e->this_update, 15, 1, fp); 
+  es_fwrite (e->this_update, 15, 1, fp);
   es_putc (':', fp);
-  es_fwrite (e->next_update, 15, 1, fp); 
+  es_fwrite (e->next_update, 15, 1, fp);
   es_putc (':', fp);
   es_fputs (e->dbfile_hash, fp);
   es_putc (':', fp);
@@ -785,7 +792,7 @@ update_dir (crl_cache_t cache)
   if (!fp)
     {
       err = gpg_error_from_errno (errno);
-      log_error (_("failed to open cache dir file `%s': %s\n"),
+      log_error (_("failed to open cache dir file '%s': %s\n"),
                  fname, strerror (errno));
       goto leave;
     }
@@ -802,7 +809,7 @@ update_dir (crl_cache_t cache)
 #ifndef HAVE_W32_SYSTEM
     struct utsname utsbuf;
 #endif
-    
+
 #ifdef HAVE_W32_SYSTEM
     nodename = "unknown";
 #else
@@ -812,12 +819,12 @@ update_dir (crl_cache_t cache)
       nodename = utsbuf.nodename;
 #endif
 
-    estream_asprintf (&tmpbuf, "DIR-tmp-%s-%u-%p.txt.tmp",
-                      nodename, (unsigned int)getpid (), &tmpbuf);
+    gpgrt_asprintf (&tmpbuf, "DIR-tmp-%s-%u-%p.txt.tmp",
+                    nodename, (unsigned int)getpid (), &tmpbuf);
     if (!tmpbuf)
       {
         err = gpg_error_from_errno (errno);
-        log_error (_("failed to create temporary cache dir file `%s': %s\n"),
+        log_error (_("failed to create temporary cache dir file '%s': %s\n"),
                    tmpfname, strerror (errno));
         goto leave;
       }
@@ -831,7 +838,7 @@ update_dir (crl_cache_t cache)
   if (!fpout)
     {
       err = gpg_error_from_errno (errno);
-      log_error (_("failed to create temporary cache dir file `%s': %s\n"),
+      log_error (_("failed to create temporary cache dir file '%s': %s\n"),
                  tmpfname, strerror (errno));
       goto leave;
     }
@@ -852,11 +859,11 @@ update_dir (crl_cache_t cache)
                  field, thus we can compare it pretty easily. */
               *endp = 0;
               e = find_entry ( cache->entries, fieldp);
-              *endp = ':'; /* Restore orginal line. */
-              if (e && e->deleted) 
+              *endp = ':'; /* Restore original line. */
+              if (e && e->deleted)
                 {
                   /* Marked for deletion, so don't write it. */
-                  e->mark = 0; 
+                  e->mark = 0;
                 }
               else if (e)
                 {
@@ -869,7 +876,7 @@ update_dir (crl_cache_t cache)
                      because they may have been added in the meantime
                      by other instances of dirmngr. */
                   es_fprintf (fpout, "# Next line added by "
-                              "another process; our pid is %lu\n", 
+                              "another process; our pid is %lu\n",
                               (unsigned long)getpid ());
                   es_fputs (line, fpout);
                   es_putc ('\n', fpout);
@@ -882,7 +889,7 @@ update_dir (crl_cache_t cache)
               es_putc ('\n', fpout);
             }
         }
-      else 
+      else
         {
           /* Write out all non CRL lines as they are. */
           es_fputs (line, fpout);
@@ -905,18 +912,18 @@ update_dir (crl_cache_t cache)
   if (lineerr)
     {
       err = lineerr;
-      log_error (_("error reading `%s': %s\n"), fname, gpg_strerror (err));
+      log_error (_("error reading '%s': %s\n"), fname, gpg_strerror (err));
       goto leave;
     }
   if (es_ferror (fp))
     {
       err = gpg_error_from_errno (errno);
-      log_error (_("error reading `%s': %s\n"), fname, strerror (errno));
+      log_error (_("error reading '%s': %s\n"), fname, strerror (errno));
     }
   if (es_ferror (fpout))
     {
       err = gpg_error_from_errno (errno);
-      log_error (_("error writing `%s': %s\n"), tmpfname, strerror (errno));
+      log_error (_("error writing '%s': %s\n"), tmpfname, strerror (errno));
     }
   if (err)
     goto leave;
@@ -927,19 +934,19 @@ update_dir (crl_cache_t cache)
   if (es_fclose (fpout))
     {
       err = gpg_error_from_errno (errno);
-      log_error (_("error closing `%s': %s\n"), tmpfname, strerror (errno));
+      log_error (_("error closing '%s': %s\n"), tmpfname, strerror (errno));
       goto leave;
     }
   fpout = NULL;
 
 #ifdef HAVE_W32_SYSTEM
   /* No atomic mv on W32 systems.  */
-  unlink (fname);
+  gnupg_remove (fname);
 #endif
   if (rename (tmpfname, fname))
     {
       err = gpg_error_from_errno (errno);
-      log_error (_("error renaming `%s' to `%s': %s\n"),
+      log_error (_("error renaming '%s' to '%s': %s\n"),
                  tmpfname, fname, strerror (errno));
       goto leave;
     }
@@ -987,13 +994,13 @@ hash_dbfile (const char *fname, unsigned char *md5buffer)
   char *buffer;
   size_t n;
   gcry_md_hd_t md5;
-  gpg_err_code_t err;
+  gpg_error_t err;
 
   buffer = xtrymalloc (65536);
   fp = buffer? es_fopen (fname, "rb") : NULL;
   if (!fp)
     {
-      log_error (_("can't hash `%s': %s\n"), fname, strerror (errno));
+      log_error (_("can't hash '%s': %s\n"), fname, strerror (errno));
       xfree (buffer);
       return -1;
     }
@@ -1011,13 +1018,13 @@ hash_dbfile (const char *fname, unsigned char *md5buffer)
   /* We better hash some information about the cache file layout in. */
   sprintf (buffer, "%.100s/%.100s:%d", DBDIR_D, DBDIRFILE, DBDIRVERSION);
   gcry_md_write (md5, buffer, strlen (buffer));
-    
+
   for (;;)
     {
       n = es_fread (buffer, 1, 65536, fp);
       if (n < 65536 && es_ferror (fp))
         {
-          log_error (_("error hashing `%s': %s\n"), fname, strerror (errno));
+          log_error (_("error hashing '%s': %s\n"), fname, strerror (errno));
           xfree (buffer);
           es_fclose (fp);
           gcry_md_close (md5);
@@ -1045,7 +1052,7 @@ check_dbfile (const char *fname, const char *md5hexvalue)
 
   if (strlen (md5hexvalue) != 32)
     {
-      log_error (_("invalid formatted checksum for `%s'\n"), fname);
+      log_error (_("invalid formatted checksum for '%s'\n"), fname);
       return -1;
     }
   unhexify (buffer1, md5hexvalue);
@@ -1059,7 +1066,7 @@ check_dbfile (const char *fname, const char *md5hexvalue)
 
 /* Open the cache file for ENTRY.  This function implements a caching
    strategy and might close unused cache files. It is required to use
-   unlock_db_file after using the file. */ 
+   unlock_db_file after using the file. */
 static struct cdb *
 lock_db_file (crl_cache_t cache, crl_cache_entry_t entry)
 {
@@ -1116,7 +1123,7 @@ lock_db_file (crl_cache_t cache, crl_cache_entry_t entry)
 
   fname = make_db_file_name (entry->issuer_hash);
   if (opt.verbose)
-    log_info (_("opening cache file `%s'\n"), fname );
+    log_info (_("opening cache file '%s'\n"), fname );
 
   if (!entry->dbfile_checked)
     {
@@ -1135,7 +1142,7 @@ lock_db_file (crl_cache_t cache, crl_cache_entry_t entry)
   fd = open (fname, O_RDONLY);
   if (fd == -1)
     {
-      log_error (_("error opening cache file `%s': %s\n"),
+      log_error (_("error opening cache file '%s': %s\n"),
                  fname, strerror (errno));
       xfree (entry->cdb);
       entry->cdb = NULL;
@@ -1144,7 +1151,7 @@ lock_db_file (crl_cache_t cache, crl_cache_entry_t entry)
     }
   if (cdb_init (entry->cdb, fd))
     {
-      log_error (_("error initializing cache file `%s' for reading: %s\n"),
+      log_error (_("error initializing cache file '%s' for reading: %s\n"),
                  fname, strerror (errno));
       xfree (entry->cdb);
       entry->cdb = NULL;
@@ -1168,7 +1175,7 @@ unlock_db_file (crl_cache_t cache, crl_cache_entry_t entry)
     log_error (_("calling unlock_db_file on a closed file\n"));
   else if (!entry->cdb_use_count)
     log_error (_("calling unlock_db_file on an unlocked file\n"));
-  else 
+  else
     {
       entry->cdb_use_count--;
       entry->cdb_lru_count++;
@@ -1189,23 +1196,23 @@ unlock_db_file (crl_cache_t cache, crl_cache_entry_t entry)
         cache->entries = enext;
       else
         eprev->next = enext;
+      /* FIXME: Do we leak ENTRY? */
     }
 }
 
 
 /* Find ISSUER_HASH in our cache FIRST. This may be used to enumerate
    the linked list we use to keep the CRLs of an issuer. */
-static crl_cache_entry_t 
+static crl_cache_entry_t
 find_entry (crl_cache_entry_t first, const char *issuer_hash)
 {
   while (first && (first->deleted || strcmp (issuer_hash, first->issuer_hash)))
     first = first->next;
-  return first;    
+  return first;
 }
 
 
-
-/* Create a new CRL cache. This fucntion is usually called only once.
+/* Create a new CRL cache. This function is usually called only once.
    never fail. */
 void
 crl_cache_init(void)
@@ -1220,7 +1227,7 @@ crl_cache_init(void)
     }
 
   err = open_dir (&cache);
-  if (err) 
+  if (err)
     log_fatal (_("failed to create a new cache object: %s\n"),
                gpg_strerror (err));
   current_cache = cache;
@@ -1229,7 +1236,7 @@ crl_cache_init(void)
 
 /* Remove the cache information and all its resources.  Note that we
    still keep the cache on disk. */
-void 
+void
 crl_cache_deinit (void)
 {
   if (current_cache)
@@ -1241,7 +1248,7 @@ crl_cache_deinit (void)
 
 
 /* Delete the cache from disk. Return 0 on success.*/
-int 
+int
 crl_cache_flush (void)
 {
   int rc;
@@ -1258,7 +1265,7 @@ crl_cache_flush (void)
    cache has not yet expired.  We use a 30 minutes threshold here so
    that invoking this function several times won't load the CRL over
    and over.  */
-static crl_cache_result_t 
+static crl_cache_result_t
 cache_isvalid (ctrl_t ctrl, const char *issuer_hash,
                const unsigned char *sn, size_t snlen,
                int force_refresh)
@@ -1290,7 +1297,7 @@ cache_isvalid (ctrl_t ctrl, const char *issuer_hash,
   if (force_refresh)
     {
       gnupg_isotime_t tmptime;
-      
+
       if (*entry->last_refresh)
         {
           gnupg_copy_time (tmptime, entry->last_refresh);
@@ -1298,7 +1305,7 @@ cache_isvalid (ctrl_t ctrl, const char *issuer_hash,
           if (strcmp (tmptime, current_time) < 0 )
             {
               log_info (_("force-crl-refresh active and %d minutes passed for"
-                          " issuer id %s; update required\n"), 
+                          " issuer id %s; update required\n"),
                         30, issuer_hash);
               return CRL_CACHE_DONTKNOW;
             }
@@ -1306,7 +1313,7 @@ cache_isvalid (ctrl_t ctrl, const char *issuer_hash,
       else
         {
           log_info (_("force-crl-refresh active for"
-                      " issuer id %s; update required\n"), 
+                      " issuer id %s; update required\n"),
                     issuer_hash);
           return CRL_CACHE_DONTKNOW;
         }
@@ -1322,7 +1329,7 @@ cache_isvalid (ctrl_t ctrl, const char *issuer_hash,
   cdb = lock_db_file (cache, entry);
   if (!cdb)
     return CRL_CACHE_DONTKNOW; /* Hmmm, not the best error code. */
-  
+
   if (!entry->dbfile_checked)
     {
       log_error (_("cached CRL for issuer id %s tampered; we need to update\n")
@@ -1332,7 +1339,7 @@ cache_isvalid (ctrl_t ctrl, const char *issuer_hash,
     }
 
   rc = cdb_find (cdb, sn, snlen);
-  if (rc == 1) 
+  if (rc == 1)
     {
       n = cdb_datalen (cdb);
       if (n != 16)
@@ -1366,7 +1373,7 @@ cache_isvalid (ctrl_t ctrl, const char *issuer_hash,
         }
       retval = CRL_CACHE_VALID;
     }
-  else 
+  else
     {
       log_error (_("error getting data from cache file: %s\n"),
                  strerror (errno));
@@ -1407,7 +1414,7 @@ cache_isvalid (ctrl_t ctrl, const char *issuer_hash,
    cache has not yet expired.  We use a 30 minutes threshold here so
    that invoking this function several times won't load the CRL over
    and over.  */
-crl_cache_result_t 
+crl_cache_result_t
 crl_cache_isvalid (ctrl_t ctrl, const char *issuer_hash, const char *serialno,
                    int force_refresh)
 {
@@ -1434,7 +1441,7 @@ crl_cache_isvalid (ctrl_t ctrl, const char *issuer_hash, const char *serialno,
     xfree (snbuf);
 
   return result;
-}  
+}
 
 
 /* Check whether the certificate CERT is valid; i.e. not listed in our
@@ -1467,7 +1474,7 @@ crl_cache_cert_isvalid (ctrl_t ctrl, ksba_cert_t cert,
   xfree (tmp);
   for (i=0,tmp=issuerhash_hex; i < 20; i++, tmp += 2)
     sprintf (tmp, "%02X", issuerhash[i]);
-  
+
   /* Get the serial number.  */
   serial = ksba_cert_get_serial (cert);
   if (!serial)
@@ -1503,9 +1510,10 @@ crl_cache_cert_isvalid (ctrl_t ctrl, ksba_cert_t cert,
     case CRL_CACHE_INVALID:
       err = gpg_error (GPG_ERR_CERT_REVOKED);
       break;
-    case CRL_CACHE_DONTKNOW: 
+    case CRL_CACHE_DONTKNOW:
       err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
-    case CRL_CACHE_CANTUSE: 
+      break;
+    case CRL_CACHE_CANTUSE:
       err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
       break;
     default:
@@ -1514,23 +1522,23 @@ crl_cache_cert_isvalid (ctrl_t ctrl, ksba_cert_t cert,
 
   xfree (serial);
   return err;
-}  
+}
 
 
 /* Prepare a hash context for the signature verification.  Input is
    the CRL and the output is the hash context MD as well as the uses
    algorithm identifier ALGO. */
 static gpg_error_t
-start_sig_check (ksba_crl_t crl, gcry_md_hd_t *md, int *algo) 
+start_sig_check (ksba_crl_t crl, gcry_md_hd_t *md, int *algo)
 {
   gpg_error_t err;
   const char *algoid;
 
   algoid = ksba_crl_get_digest_algo (crl);
   *algo = gcry_md_map_name (algoid);
-  if (!*algo) 
+  if (!*algo)
     {
-      log_error (_("unknown hash algorithm `%s'\n"), algoid? algoid:"?");
+      log_error (_("unknown hash algorithm '%s'\n"), algoid? algoid:"?");
       return gpg_error (GPG_ERR_DIGEST_ALGO);
     }
 
@@ -1544,7 +1552,7 @@ start_sig_check (ksba_crl_t crl, gcry_md_hd_t *md, int *algo)
   if (DBG_HASHING)
     gcry_md_debug (*md, "hash.cert");
 
-  ksba_crl_set_hash_function (crl, HASH_FNC, *md);  
+  ksba_crl_set_hash_function (crl, HASH_FNC, *md);
   return 0;
 }
 
@@ -1572,33 +1580,33 @@ finish_sig_check (ksba_crl_t crl, gcry_md_hd_t md, int algo,
   /* Get and convert the signature value. */
   sigval = ksba_crl_get_sig_val (crl);
   n = gcry_sexp_canon_len (sigval, 0, NULL, NULL);
-  if (!n) 
+  if (!n)
     {
       log_error (_("got an invalid S-expression from libksba\n"));
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto leave;
     }
   err = gcry_sexp_sscan (&s_sig, NULL, sigval, n);
-  if (err) 
+  if (err)
     {
       log_error (_("converting S-expression failed: %s\n"),
                  gcry_strerror (err));
       goto leave;
     }
-       
+
   /* Get and convert the public key for the issuer certificate. */
   if (DBG_X509)
     dump_cert ("crl_issuer_cert", issuer_cert);
   pubkey = ksba_cert_get_public_key (issuer_cert);
   n = gcry_sexp_canon_len (pubkey, 0, NULL, NULL);
-  if (!n) 
+  if (!n)
     {
       log_error (_("got an invalid S-expression from libksba\n"));
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto leave;
     }
   err = gcry_sexp_sscan (&s_pkey, NULL, pubkey, n);
-  if (err) 
+  if (err)
     {
       log_error (_("converting S-expression failed: %s\n"),
                  gcry_strerror (err));
@@ -1610,10 +1618,10 @@ finish_sig_check (ksba_crl_t crl, gcry_md_hd_t md, int algo,
   for (i = 0; *s && i < sizeof(algoname) - 1; s++, i++)
     algoname[i] = ascii_tolower (*s);
   algoname[i] = 0;
-  err = gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))", 
+  err = gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))",
                          algoname,
                          gcry_md_get_algo_dlen (algo), gcry_md_read (md, algo));
-  if (err) 
+  if (err)
     {
       log_error (_("creating S-expression failed: %s\n"), gcry_strerror (err));
       goto leave;
@@ -1660,21 +1668,21 @@ abort_sig_check (ksba_crl_t crl, gcry_md_hd_t md)
    error.  R_TRUST_ANCHOR is set on exit to NULL or a string with the
    hexified fingerprint of the root certificate, if checking this
    certificate for trustiness is required.
-*/ 
-static int 
+*/
+static int
 crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
                   struct cdb_make *cdb, const char *fname,
                   char **r_crlissuer,
                   ksba_isotime_t thisupdate, ksba_isotime_t nextupdate,
                   char **r_trust_anchor)
-{  
+{
   gpg_error_t err;
   ksba_stop_reason_t stopreason;
   ksba_cert_t crlissuer_cert = NULL;
   gcry_md_hd_t md = NULL;
   int algo = 0;
   size_t n;
-  
+
   (void)fname;
 
   *r_crlissuer = NULL;
@@ -1695,21 +1703,22 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
         {
         case KSBA_SR_BEGIN_ITEMS:
           {
-            if (start_sig_check (crl, &md, &algo ))
+            err = start_sig_check (crl, &md, &algo);
+            if (err)
               goto failure;
-          
+
             err = ksba_crl_get_update_times (crl, thisupdate, nextupdate);
             if (err)
               {
                 log_error (_("error getting update times of CRL: %s\n"),
-                           gpg_strerror (err));          
+                           gpg_strerror (err));
                 err = gpg_error (GPG_ERR_INV_CRL);
                 goto failure;
               }
 
             if (opt.verbose || !*nextupdate)
-              log_info (_("update times of this CRL: this=%s next=%s\n"), 
-                        thisupdate, nextupdate);   
+              log_info (_("update times of this CRL: this=%s next=%s\n"),
+                        thisupdate, nextupdate);
             if (!*nextupdate)
               {
                 log_info (_("nextUpdate not given; "
@@ -1719,7 +1728,7 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
               }
           }
           break;
-      
+
         case KSBA_SR_GOT_ITEM:
           {
             ksba_sexp_t serial;
@@ -1742,7 +1751,7 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
             if (!p)
               BUG ();
             record[0] = (reason & 0xff);
-            memcpy (record+1, rdate, 15); 
+            memcpy (record+1, rdate, 15);
             rc = cdb_make_add (cdb, p, n, record, 1+15);
             if (rc)
               {
@@ -1756,10 +1765,10 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
             ksba_free (serial);
           }
           break;
-      
+
         case KSBA_SR_END_ITEMS:
           break;
-      
+
         case KSBA_SR_READY:
           {
             char *crlissuer;
@@ -1791,7 +1800,7 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
                 if (opt.verbose)
                   log_info (_("locating CRL issuer certificate by "
                               "authorityKeyIdentifier\n"));
-                
+
                 s = ksba_name_enum (authid, 0);
                 if (s && *authidsn)
                   crlissuer_cert = find_cert_bysn (ctrl, s, authidsn);
@@ -1830,11 +1839,11 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
                 err = gpg_error (GPG_ERR_MISSING_CERT);
                 goto failure;
               }
-        
+
             err = finish_sig_check (crl, md, algo, crlissuer_cert);
             if (err)
               {
-                log_error (_("CRL signature verification failed: %s\n"), 
+                log_error (_("CRL signature verification failed: %s\n"),
                            gpg_strerror (err));
                 goto failure;
               }
@@ -1846,20 +1855,20 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
             if (err)
               {
                 log_error (_("error checking validity of CRL "
-                             "issuer certificate: %s\n"), 
+                             "issuer certificate: %s\n"),
                            gpg_strerror (err));
                 goto failure;
               }
 
           }
           break;
-      
+
         default:
           log_debug ("crl_parse_insert: unknown stop reason\n");
           err = gpg_error (GPG_ERR_BUG);
           goto failure;
         }
-    } 
+    }
   while (stopreason != KSBA_SR_READY);
   assert (!err);
 
@@ -1914,7 +1923,7 @@ get_auth_key_id (ksba_crl_t crl, char **serialno)
 
   if (!name)
     return xstrdup ("");
-  
+
   length = 0;
   for (idx=0; (s = ksba_name_enum (name, idx)); idx++)
     {
@@ -1943,7 +1952,19 @@ get_auth_key_id (ksba_crl_t crl, char **serialno)
 
 /* Insert the CRL retrieved using URL into the cache specified by
    CACHE.  The CRL itself will be read from the stream FP and is
-   expected in binary format. */
+   expected in binary format.
+
+   Called by:
+      crl_cache_load
+         cmd_loadcrl
+         --load-crl
+      crl_cache_reload_crl
+         cmd_isvalid
+         cmd_checkcrl
+      cmd_loadcrl
+      --fetch-crl
+
+ */
 gpg_error_t
 crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
 {
@@ -1970,7 +1991,7 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
   /* FIXME: We should acquire a mutex for the URL, so that we don't
      simultaneously enter the same CRL twice.  However this needs to be
      interweaved with the checking function.*/
+
   err2 = 0;
 
   err = ksba_crl_new (&crl);
@@ -1979,7 +2000,7 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
       log_error (_("ksba_crl_new failed: %s\n"), gpg_strerror (err));
       goto leave;
     }
-  
+
   err = ksba_crl_set_reader (crl, reader);
   if ( err )
     {
@@ -2004,8 +2025,8 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
       nodename = utsbuf.nodename;
 #endif
 
-    estream_asprintf (&tmpfname, "crl-tmp-%s-%u-%p.db.tmp",
-                      nodename, (unsigned int)getpid (), &tmpfname);
+    gpgrt_asprintf (&tmpfname, "crl-tmp-%s-%u-%p.db.tmp",
+                    nodename, (unsigned int)getpid (), &tmpfname);
     if (!tmpfname)
       {
         err = gpg_error_from_syserror ();
@@ -2017,11 +2038,11 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
     fname = make_filename (opt.homedir_cache, DBDIR_D, tmpfname, NULL);
     xfree (tmpfname);
     if (!gnupg_remove (fname))
-      log_info (_("removed stale temporary cache file `%s'\n"), fname);
-    else if (errno != ENOENT) 
+      log_info (_("removed stale temporary cache file '%s'\n"), fname);
+    else if (errno != ENOENT)
       {
         err = gpg_error_from_syserror ();
-        log_error (_("problem removing stale temporary cache file `%s': %s\n"),
+        log_error (_("problem removing stale temporary cache file '%s': %s\n"),
                    fname, gpg_strerror (err));
         goto leave;
       }
@@ -2031,7 +2052,7 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
   if (fd_cdb == -1)
     {
       err = gpg_error_from_errno (errno);
-      log_error (_("error creating temporary cache file `%s': %s\n"),
+      log_error (_("error creating temporary cache file '%s': %s\n"),
                  fname, strerror (errno));
       goto leave;
     }
@@ -2051,14 +2072,14 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
   if (cdb_make_finish (&cdb))
     {
       err = gpg_error_from_errno (errno);
-      log_error (_("error finishing temporary cache file `%s': %s\n"),
+      log_error (_("error finishing temporary cache file '%s': %s\n"),
                  fname, strerror (errno));
       goto leave;
     }
   if (close (fd_cdb))
     {
       err = gpg_error_from_errno (errno);
-      log_error (_("error closing temporary cache file `%s': %s\n"),
+      log_error (_("error closing temporary cache file '%s': %s\n"),
                  fname, strerror (errno));
       goto leave;
     }
@@ -2108,7 +2129,7 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
         err2 = gpg_error (GPG_ERR_INV_CRL);
       invalidate_crl |= 2;
     }
-  if (gpg_err_code (err) == GPG_ERR_EOF 
+  if (gpg_err_code (err) == GPG_ERR_EOF
       || gpg_err_code (err) == GPG_ERR_NO_DATA )
     err = 0;
   if (err)
@@ -2129,9 +2150,9 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
       err = gpg_error_from_syserror ();
       goto leave;
     }
-  entry->release_ptr = xtrymalloc (strlen (issuer_hash) + 1 
+  entry->release_ptr = xtrymalloc (strlen (issuer_hash) + 1
                                    + strlen (issuer) + 1
-                                   + strlen (url) + 1 
+                                   + strlen (url) + 1
                                    + strlen (checksum) + 1);
   if (!entry->release_ptr)
     {
@@ -2145,8 +2166,8 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
   entry->url = stpcpy (entry->issuer, issuer) + 1;
   entry->dbfile_hash = stpcpy (entry->url, url) + 1;
   strcpy (entry->dbfile_hash, checksum);
-  gnupg_copy_time (entry->this_update, thisupdate); 
-  gnupg_copy_time (entry->next_update, nextupdate); 
+  gnupg_copy_time (entry->this_update, thisupdate);
+  gnupg_copy_time (entry->next_update, nextupdate);
   gnupg_copy_time (entry->last_refresh, current_time);
   entry->crl_number = get_crl_number (crl);
   entry->authority_issuer = get_auth_key_id (crl, &entry->authority_serialno);
@@ -2160,18 +2181,43 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
      somehow into the list. */
   for (e = cache->entries; (e=find_entry (e, entry->issuer_hash)); e = e->next)
     e->deleted = 1;
-  
+
   /* Rename the temporary DB to the real name. */
   newfname = make_db_file_name (entry->issuer_hash);
   if (opt.verbose)
-    log_info (_("creating cache file `%s'\n"), newfname);
+    log_info (_("creating cache file '%s'\n"), newfname);
+
+  /* Just in case close unused matching files.  Actually we need this
+     only under Windows but saving file descriptors is never bad.  */
+  {
+    int any;
+    do
+      {
+        any = 0;
+        for (e = cache->entries; e; e = e->next)
+          if (!e->cdb_use_count && e->cdb
+              && !strcmp (e->issuer_hash, entry->issuer_hash))
+            {
+              int fd = cdb_fileno (e->cdb);
+              cdb_free (e->cdb);
+              xfree (e->cdb);
+              e->cdb = NULL;
+              if (close (fd))
+                log_error (_("error closing cache file: %s\n"),
+                           strerror(errno));
+              any = 1;
+              break;
+            }
+      }
+    while (any);
+  }
 #ifdef HAVE_W32_SYSTEM
-  unlink (newfname);
+  gnupg_remove (newfname);
 #endif
   if (rename (fname, newfname))
     {
       err = gpg_error_from_syserror ();
-      log_error (_("problem renaming `%s' to `%s': %s\n"),
+      log_error (_("problem renaming '%s' to '%s': %s\n"),
                  fname, newfname, gpg_strerror (err));
       goto leave;
     }
@@ -2225,8 +2271,8 @@ list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, estream_t fp)
   es_fprintf (fp, _("Begin CRL dump (retrieved via %s)\n"), e->url );
   es_fprintf (fp, " Issuer:\t%s\n", e->issuer );
   es_fprintf (fp, " Issuer Hash:\t%s\n", e->issuer_hash );
-  es_fprintf (fp, " This Update:\t%s\n", e->this_update ); 
-  es_fprintf (fp, " Next Update:\t%s\n", e->next_update ); 
+  es_fprintf (fp, " This Update:\t%s\n", e->this_update );
+  es_fprintf (fp, " Next Update:\t%s\n", e->next_update );
   es_fprintf (fp, " CRL Number :\t%s\n", e->crl_number? e->crl_number: "none");
   es_fprintf (fp, " AuthKeyId  :\t%s\n",
               e->authority_serialno? e->authority_serialno:"none");
@@ -2240,7 +2286,7 @@ list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, estream_t fp)
           es_putc (*s, fp);
       es_putc ('\n', fp);
     }
-  es_fprintf (fp, " Trust Check:\t%s\n", 
+  es_fprintf (fp, " Trust Check:\t%s\n",
               !e->user_trust_req? "[system]" :
               e->check_trust_anchor? e->check_trust_anchor:"[missing]");
 
@@ -2258,7 +2304,7 @@ list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, estream_t fp)
     return gpg_error (GPG_ERR_GENERAL);
 
   if (!e->dbfile_checked)
-    es_fprintf (fp, _(" ERROR: This cached CRL may has been tampered with!\n"));
+    es_fprintf (fp, _(" ERROR: This cached CRL may have been tampered with!\n"));
 
   es_putc ('\n', fp);
 
@@ -2288,7 +2334,7 @@ list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, estream_t fp)
           warn = 1;
           continue;
         }
-    
+
       n = cdb_keylen (cdb);
       if (n > sizeof keyrecord)
         n = sizeof keyrecord;
@@ -2304,26 +2350,26 @@ list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, estream_t fp)
       for (i = 0; i < n; i++)
         es_fprintf (fp, "%02X", keyrecord[i]);
       es_fputs (":\t reasons( ", fp);
-    
+
       if (reason & KSBA_CRLREASON_UNSPECIFIED)
         es_fputs( "unspecified ", fp ), any = 1;
       if (reason & KSBA_CRLREASON_KEY_COMPROMISE )
-        es_fputs( "key_compromise ", fp ), any = 1; 
+        es_fputs( "key_compromise ", fp ), any = 1;
       if (reason & KSBA_CRLREASON_CA_COMPROMISE )
-        es_fputs( "ca_compromise ", fp ), any = 1; 
+        es_fputs( "ca_compromise ", fp ), any = 1;
       if (reason & KSBA_CRLREASON_AFFILIATION_CHANGED )
-        es_fputs( "affiliation_changed ", fp ), any = 1; 
+        es_fputs( "affiliation_changed ", fp ), any = 1;
       if (reason & KSBA_CRLREASON_SUPERSEDED )
-        es_fputs( "superseeded", fp ), any = 1; 
+        es_fputs( "superseeded", fp ), any = 1;
       if (reason & KSBA_CRLREASON_CESSATION_OF_OPERATION )
-        es_fputs( "cessation_of_operation", fp ), any = 1; 
+        es_fputs( "cessation_of_operation", fp ), any = 1;
       if (reason & KSBA_CRLREASON_CERTIFICATE_HOLD )
-        es_fputs( "certificate_hold", fp ), any = 1; 
+        es_fputs( "certificate_hold", fp ), any = 1;
       if (reason && !any)
-        es_fputs( "other", fp ); 
-      
+        es_fputs( "other", fp );
+
       es_fprintf (fp, ") rdate: %.15s\n", record+1);
-    } 
+    }
   if (rc)
     log_error (_("error reading cache entry from db: %s\n"), strerror (rc));
 
@@ -2337,8 +2383,8 @@ list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, estream_t fp)
 
 /* Print the contents of the CRL CACHE in a human readable format to
    stream FP. */
-gpg_error_t 
-crl_cache_list (estream_t fp) 
+gpg_error_t
+crl_cache_list (estream_t fp)
 {
   crl_cache_t cache = get_current_cache ();
   crl_cache_entry_t entry;
@@ -2346,7 +2392,7 @@ crl_cache_list (estream_t fp)
 
   for (entry = cache->entries;
        entry && !entry->deleted && !err;
-       entry = entry->next ) 
+       entry = entry->next )
     err = list_one_crl_entry (cache, entry, fp);
 
   return err;
@@ -2365,7 +2411,7 @@ crl_cache_load (ctrl_t ctrl, const char *filename)
   if (!fp)
     {
       err = gpg_error_from_errno (errno);
-      log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
+      log_error (_("can't open '%s': %s\n"), filename, strerror (errno));
       return err;
     }
 
@@ -2383,7 +2429,7 @@ crl_cache_load (ctrl_t ctrl, const char *filename)
 /* Locate the corresponding CRL for the certificate CERT, read and
    verify the CRL and store it in the cache.  */
 gpg_error_t
-crl_cache_reload_crl (ctrl_t ctrl, ksba_cert_t cert) 
+crl_cache_reload_crl (ctrl_t ctrl, ksba_cert_t cert)
 {
   gpg_error_t err;
   ksba_reader_t reader = NULL;
@@ -2404,7 +2450,7 @@ crl_cache_reload_crl (ctrl_t ctrl, ksba_cert_t cert)
                                                 &distpoint,
                                                 &issuername, NULL )))
     {
-      int name_seq; 
+      int name_seq;
       gpg_error_t last_err = 0;
 
       if (!distpoint && !issuername)
@@ -2426,7 +2472,7 @@ crl_cache_reload_crl (ctrl_t ctrl, ksba_cert_t cert)
           distpoint_uri = ksba_name_get_uri (distpoint, name_seq);
           if (!distpoint_uri)
             continue;
-          
+
           if (!strncmp (distpoint_uri, "ldap:", 5)
               || !strncmp (distpoint_uri, "ldaps:", 6))
             {
@@ -2441,11 +2487,11 @@ crl_cache_reload_crl (ctrl_t ctrl, ksba_cert_t cert)
             }
           else
             continue; /* Skip unknown schemes. */
-          
+
           any_dist_point = 1;
-          
+
           if (opt.verbose)
-            log_info ("fetching CRL from `%s'\n", distpoint_uri);
+            log_info ("fetching CRL from '%s'\n", distpoint_uri);
           err = crl_fetch (ctrl, distpoint_uri, &reader);
           if (err)
             {
@@ -2454,10 +2500,10 @@ crl_cache_reload_crl (ctrl_t ctrl, ksba_cert_t cert)
               last_err = err;
               continue; /* with the next name. */
             }
-          
+
           if (opt.verbose)
             log_info ("inserting CRL (reader %p)\n", reader);
-          err = crl_cache_insert (ctrl, distpoint_uri, reader); 
+          err = crl_cache_insert (ctrl, distpoint_uri, reader);
           if (err)
             {
               log_error (_("crl_cache_insert via DP failed: %s\n"),
@@ -2473,14 +2519,17 @@ crl_cache_reload_crl (ctrl_t ctrl, ksba_cert_t cert)
           err = last_err;
           goto leave;
         }
-      
+
       ksba_name_release (distpoint); distpoint = NULL;
 
       /* We don't do anything with issuername_uri yet but we keep the
          code for documentation. */
-      issuername_uri =  ksba_name_get_uri (issuername, 0); 
+      issuername_uri =  ksba_name_get_uri (issuername, 0);
       ksba_name_release (issuername); issuername = NULL;
 
+      /* Close the reader.  */
+      crl_close_reader (reader);
+      reader = NULL;
     }
   if (gpg_err_code (err) == GPG_ERR_EOF)
     err = 0;
@@ -2490,18 +2539,15 @@ crl_cache_reload_crl (ctrl_t ctrl, ksba_cert_t cert)
     {
       if (opt.verbose)
         log_info ("no distribution point - trying issuer name\n");
-      
-      if (reader)
-        {
-          crl_close_reader (reader);
-          reader = NULL;
-        }
+
+      crl_close_reader (reader);
+      reader = NULL;
 
       issuer = ksba_cert_get_issuer (cert, 0);
-      if (!issuer) 
+      if (!issuer)
         {
           log_error ("oops: issuer missing in certificate\n");
-          err = gpg_error (GPG_ERR_INV_CERT_OBJ); 
+          err = gpg_error (GPG_ERR_INV_CERT_OBJ);
           goto leave;
         }
 
@@ -2527,13 +2573,11 @@ crl_cache_reload_crl (ctrl_t ctrl, ksba_cert_t cert)
     }
 
  leave:
-  if (reader)
-    crl_close_reader (reader);
+  crl_close_reader (reader);
   xfree (distpoint_uri);
   xfree (issuername_uri);
-  ksba_name_release (distpoint); 
-  ksba_name_release (issuername); 
+  ksba_name_release (distpoint);
+  ksba_name_release (issuername);
   ksba_free (issuer);
   return err;
 }
-