static int tls_check_one_certificate (const gnutls_datum_t *certdata,
                                      gnutls_certificate_status_t certstat,
                                      const char* hostname, int idx, int len)
{
  int certerr, savedcert;
  gnutls_x509_crt_t cert;
  char buf[SHORT_STRING];
  char fpbuf[SHORT_STRING];
  size_t buflen;
  char dn_common_name[SHORT_STRING];
  char dn_email[SHORT_STRING];
  char dn_organization[SHORT_STRING];
  char dn_organizational_unit[SHORT_STRING];
  char dn_locality[SHORT_STRING];
  char dn_province[SHORT_STRING];
  char dn_country[SHORT_STRING];
  time_t t;
  char datestr[30];
  MUTTMENU *menu;
  char helpstr[LONG_STRING];
  char title[STRING];
  BUFFER *drow = NULL;
  FILE *fp;
  gnutls_datum_t pemdata;
  int done, ret, reset_ignoremacro = 0;

  if (!tls_check_preauth (certdata, certstat, hostname, idx, &certerr,
                          &savedcert))
    return 1;

  /* interactive check from user */
  if (gnutls_x509_crt_init (&cert) < 0)
  {
    mutt_error (_("Error initialising gnutls certificate data"));
    mutt_sleep (2);
    return 0;
  }

  if (gnutls_x509_crt_import (cert, certdata, GNUTLS_X509_FMT_DER) < 0)
  {
    mutt_error (_("Error processing certificate data"));
    mutt_sleep (2);
    gnutls_x509_crt_deinit (cert);
    return 0;
  }

  drow = mutt_buffer_pool_get ();

  menu = mutt_new_menu (MENU_GENERIC);
  mutt_push_current_menu (menu);


  buflen = sizeof (dn_common_name);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
                                     dn_common_name, &buflen) != 0)
    dn_common_name[0] = '\0';
  buflen = sizeof (dn_email);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
                                     dn_email, &buflen) != 0)
    dn_email[0] = '\0';
  buflen = sizeof (dn_organization);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0,
                                     dn_organization, &buflen) != 0)
    dn_organization[0] = '\0';
  buflen = sizeof (dn_organizational_unit);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
                                     dn_organizational_unit, &buflen) != 0)
    dn_organizational_unit[0] = '\0';
  buflen = sizeof (dn_locality);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0,
                                     dn_locality, &buflen) != 0)
    dn_locality[0] = '\0';
  buflen = sizeof (dn_province);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
                                     dn_province, &buflen) != 0)
    dn_province[0] = '\0';
  buflen = sizeof (dn_country);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
                                     dn_country, &buflen) != 0)
    dn_country[0] = '\0';

  mutt_menu_add_dialog_row (menu, _("This certificate belongs to:"));
  mutt_buffer_printf (drow, "   %s  %s", dn_common_name, dn_email);
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));
  mutt_buffer_printf (drow, "   %s", dn_organization);
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));
  mutt_buffer_printf (drow, "   %s", dn_organizational_unit);
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));
  mutt_buffer_printf (drow, "   %s  %s  %s",
            dn_locality, dn_province, dn_country);
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));


  buflen = sizeof (dn_common_name);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
                                            dn_common_name, &buflen) != 0)
    dn_common_name[0] = '\0';
  buflen = sizeof (dn_email);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
                                            dn_email, &buflen) != 0)
    dn_email[0] = '\0';
  buflen = sizeof (dn_organization);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0,
                                            dn_organization, &buflen) != 0)
    dn_organization[0] = '\0';
  buflen = sizeof (dn_organizational_unit);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
                                            dn_organizational_unit, &buflen) != 0)
    dn_organizational_unit[0] = '\0';
  buflen = sizeof (dn_locality);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0,
                                            dn_locality, &buflen) != 0)
    dn_locality[0] = '\0';
  buflen = sizeof (dn_province);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
                                            dn_province, &buflen) != 0)
    dn_province[0] = '\0';
  buflen = sizeof (dn_country);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
                                            dn_country, &buflen) != 0)
    dn_country[0] = '\0';

  mutt_menu_add_dialog_row (menu, "");
  mutt_menu_add_dialog_row (menu, _("This certificate was issued by:"));
  mutt_buffer_printf (drow, "   %s  %s", dn_common_name, dn_email);
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));
  mutt_buffer_printf (drow, "   %s", dn_organization);
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));
  mutt_buffer_printf (drow, "   %s", dn_organizational_unit);
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));
  mutt_buffer_printf (drow, "   %s  %s  %s",
            dn_locality, dn_province, dn_country);
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));


  mutt_menu_add_dialog_row (menu, "");
  mutt_menu_add_dialog_row (menu, _("This certificate is valid"));

  t = gnutls_x509_crt_get_activation_time (cert);
  mutt_buffer_printf (drow, _("   from %s"),
	    tls_make_date (t, datestr, 30));
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));

  t = gnutls_x509_crt_get_expiration_time (cert);
  mutt_buffer_printf (drow, _("     to %s"),
	    tls_make_date (t, datestr, 30));
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));


  fpbuf[0] = '\0';
  tls_fingerprint (GNUTLS_DIG_SHA, fpbuf, sizeof (fpbuf), certdata);
  mutt_buffer_printf (drow, _("SHA1 Fingerprint: %s"), fpbuf);
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));
  fpbuf[0] = '\0';
  fpbuf[40] = '\0';  /* Ensure the second printed line is null terminated */
  tls_fingerprint (GNUTLS_DIG_SHA256, fpbuf, sizeof (fpbuf), certdata);
  fpbuf[39] = '\0';  /* Divide into two lines of output */
  mutt_buffer_printf (drow, "%s%s", _("SHA256 Fingerprint: "), fpbuf);
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));
  mutt_buffer_printf (drow, "%*s%s",
            (int)mutt_strlen (_("SHA256 Fingerprint: ")), "", fpbuf + 40);
  mutt_menu_add_dialog_row (menu, mutt_b2s (drow));


  if (certerr)
    mutt_menu_add_dialog_row (menu, "");
  if (certerr & CERTERR_NOTYETVALID)
    mutt_menu_add_dialog_row (menu, _("WARNING: Server certificate is not yet valid"));
  if (certerr & CERTERR_EXPIRED)
    mutt_menu_add_dialog_row (menu, _("WARNING: Server certificate has expired"));
  if (certerr & CERTERR_REVOKED)
    mutt_menu_add_dialog_row (menu, _("WARNING: Server certificate has been revoked"));
  if (certerr & CERTERR_HOSTNAME)
    mutt_menu_add_dialog_row (menu, _("WARNING: Server hostname does not match certificate"));
  if (certerr & CERTERR_SIGNERNOTCA)
    mutt_menu_add_dialog_row (menu, _("WARNING: Signer of server certificate is not a CA"));
  if (certerr & CERTERR_INSECUREALG)
    mutt_menu_add_dialog_row (menu,
                              _("Warning: Server certificate was signed using an insecure algorithm"));

  snprintf (title, sizeof (title),
            _("SSL Certificate check (certificate %d of %d in chain)"),
            len - idx, len);
  menu->title = title;
  /* certificates with bad dates, or that are revoked, must be
     accepted manually each and every time */
  if (SslCertFile && !savedcert
      && !(certerr & (CERTERR_EXPIRED | CERTERR_NOTYETVALID
                      | CERTERR_REVOKED)))
  {
    menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always");
    /* L10N:
     * These three letters correspond to the choices in the string:
     * (r)eject, accept (o)nce, (a)ccept always.
     * This is an interactive certificate confirmation prompt for
     * a GNUTLS connection.
     */
    menu->keys = _("roa");
  }
  else
  {
    menu->prompt = _("(r)eject, accept (o)nce");
    /* L10N:
     * These two letters correspond to the choices in the string:
     * (r)eject, accept (o)nce.
     * These is an interactive certificate confirmation prompt for
     * a GNUTLS connection.
     */
    menu->keys = _("ro");
  }

  helpstr[0] = '\0';
  mutt_make_help (buf, sizeof (buf), _("Exit  "), MENU_GENERIC, OP_EXIT);
  safe_strcat (helpstr, sizeof (helpstr), buf);
  mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP);
  safe_strcat (helpstr, sizeof (helpstr), buf);
  menu->help = helpstr;

  done = 0;
  if (!option (OPTIGNOREMACROEVENTS))
  {
    set_option (OPTIGNOREMACROEVENTS);
    reset_ignoremacro = 1;
  }
  while (!done)
  {
    switch (mutt_menuLoop (menu))
    {
      case -1:			/* abort */
      case OP_MAX + 1:		/* reject */
      case OP_EXIT:
        done = 1;
        break;
      case OP_MAX + 3:		/* accept always */
        done = 0;
        if ((fp = fopen (SslCertFile, "a")))
	{
	  /* save hostname if necessary */
	  if (certerr & CERTERR_HOSTNAME)
	  {
            fpbuf[0] = '\0';
            tls_fingerprint (GNUTLS_DIG_MD5, fpbuf, sizeof (fpbuf), certdata);
	    fprintf(fp, "#H %s %s\n", hostname, fpbuf);
	    done = 1;
	  }
          /* Save the cert for all other errors */
	  if (certerr ^ CERTERR_HOSTNAME)
	  {
            done = 0;
	    ret = gnutls_pem_base64_encode_alloc ("CERTIFICATE", certdata,
                                                  &pemdata);
	    if (ret == 0)
	    {
	      if (fwrite (pemdata.data, pemdata.size, 1, fp) == 1)
	      {
		done = 1;
	      }
              gnutls_free (pemdata.data);
	    }
	  }
	  safe_fclose (&fp);
	}
	if (!done)
        {
	  mutt_error (_("Warning: Couldn't save certificate"));
	  mutt_sleep (2);
	}
	else
        {
	  mutt_message (_("Certificate saved"));
	  mutt_sleep (0);
	}
        /* fall through */
      case OP_MAX + 2:		/* accept once */
        done = 2;
        break;
    }
  }
  if (reset_ignoremacro)
    unset_option (OPTIGNOREMACROEVENTS);

  mutt_buffer_pool_release (&drow);
  mutt_pop_current_menu (menu);
  mutt_menuDestroy (&menu);
  gnutls_x509_crt_deinit (cert);

  return (done == 2) ? 1 : 0;
}