static void
infinoted_plugin_certificate_auth_certificate_func(InfXmppConnection* xmpp,
                                                   gnutls_session_t session,
                                                   InfCertificateChain* chain,
                                                   gpointer user_data)
{
  InfinotedPluginCertificateAuth* plugin;
  int res;
  int verify_result;
  GError* error;

  plugin = (InfinotedPluginCertificateAuth*)user_data;

  if(chain != NULL)
  {
    /* Note that we don't require client certificates to be signed by a CA.
     * We only require them to be signed by one of the certificates in our
     * list, but we don't care whether that's a CA or not. A common use case
     * is to sign client certificates with our own server certificate. */
    res = gnutls_x509_crt_list_verify(
      inf_certificate_chain_get_raw(chain),
      inf_certificate_chain_get_n_certificates(chain),
      plugin->cas,
      plugin->n_cas,
      NULL,
      0,
      GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT | GNUTLS_VERIFY_DISABLE_CA_SIGN,
      &verify_result
    );

    error = NULL;

    if(res != GNUTLS_E_SUCCESS)
      inf_gnutls_set_error(&error, res);
    else if( (verify_result & GNUTLS_CERT_INVALID) != 0)
      inf_gnutls_certificate_verification_set_error(&error, res);

    if(error != NULL)
    {
      inf_xmpp_connection_certificate_verify_cancel(xmpp, error);
      g_error_free(error);
    }
    else
    {
      inf_xmpp_connection_certificate_verify_continue(xmpp);
    }
  }
  else
  {
    /* If we do not accept unauthenticated clients, then GnuTLS should have
     * blocked the connection already, since we set the certificate request
     * to GNUTLS_CERT_REQUIRE in that case. */
    g_assert(plugin->accept_unauthenticated_clients == TRUE);
    inf_xmpp_connection_certificate_verify_continue(xmpp);
  }
}
Пример #2
0
static int
qcrypto_tls_creds_check_cert_pair(gnutls_x509_crt_t cert,
                                  const char *certFile,
                                  gnutls_x509_crt_t *cacerts,
                                  size_t ncacerts,
                                  const char *cacertFile,
                                  bool isServer,
                                  Error **errp)
{
    unsigned int status;

    if (gnutls_x509_crt_list_verify(&cert, 1,
                                    cacerts, ncacerts,
                                    NULL, 0,
                                    0, &status) < 0) {
        error_setg(errp, isServer ?
                   "Unable to verify server certificate %s against "
                   "CA certificate %s" :
                   "Unable to verify client certificate %s against "
                   "CA certificate %s",
                   certFile, cacertFile);
        return -1;
    }

    if (status != 0) {
        const char *reason = "Invalid certificate";

        if (status & GNUTLS_CERT_INVALID) {
            reason = "The certificate is not trusted";
        }

        if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
            reason = "The certificate hasn't got a known issuer";
        }

        if (status & GNUTLS_CERT_REVOKED) {
            reason = "The certificate has been revoked";
        }

#ifndef GNUTLS_1_0_COMPAT
        if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
            reason = "The certificate uses an insecure algorithm";
        }
#endif

        error_setg(errp,
                   "Our own certificate %s failed validation against %s: %s",
                   certFile, cacertFile, reason);
        return -1;
    }

    return 0;
}
static void
perform_verification (EmpathyTLSVerifier *self,
        GcrCertificateChain *chain)
{
  gboolean ret = FALSE;
  EmpTLSCertificateRejectReason reason =
    EMP_TLS_CERTIFICATE_REJECT_REASON_UNKNOWN;
  gnutls_x509_crt_t *list, *anchors;
  guint n_list, n_anchors;
  guint verify_output;
  gint res;
  gint i;
  gboolean matched = FALSE;
  EmpathyTLSVerifierPriv *priv = GET_PRIV (self);

  DEBUG ("Performing verification");
  debug_certificate_chain (chain);

  list = anchors = NULL;
  n_list = n_anchors = 0;

  /*
   * If the first certificate is an pinned certificate then we completely
   * ignore the rest of the verification process.
   */
  if (gcr_certificate_chain_get_status (chain) == GCR_CERTIFICATE_CHAIN_PINNED)
    {
      DEBUG ("Found pinned certificate for %s", priv->hostname);
      complete_verification (self);
      goto out;
  }

  build_certificate_list_for_gnutls (chain, &list, &n_list,
          &anchors, &n_anchors);
  if (list == NULL || n_list == 0) {
      g_warn_if_reached ();
      abort_verification (self, EMP_TLS_CERTIFICATE_REJECT_REASON_UNKNOWN);
      goto out;
  }

  verify_output = 0;
  res = gnutls_x509_crt_list_verify (list, n_list, anchors, n_anchors,
           NULL, 0, 0, &verify_output);
  ret = verification_output_to_reason (res, verify_output, &reason);

  DEBUG ("Certificate verification gave result %d with reason %u", ret,
          reason);

  if (!ret) {
      abort_verification (self, reason);
      goto out;
  }

  /* now check if the certificate matches one of the reference identities. */
  if (priv->reference_identities != NULL)
    {
      for (i = 0, matched = FALSE; priv->reference_identities[i] != NULL; ++i)
        {
          if (gnutls_x509_crt_check_hostname (list[0],
                  priv->reference_identities[i]) == 1)
            {
              matched = TRUE;
              break;
            }
        }
    }

  if (!matched)
    {
      gchar *certified_hostname;

      certified_hostname = empathy_get_x509_certificate_hostname (list[0]);
      tp_asv_set_string (priv->details,
          "expected-hostname", priv->hostname);
      tp_asv_set_string (priv->details,
          "certificate-hostname", certified_hostname);

      DEBUG ("Hostname mismatch: got %s but expected %s",
          certified_hostname, priv->hostname);

      g_free (certified_hostname);
      abort_verification (self,
              EMP_TLS_CERTIFICATE_REJECT_REASON_HOSTNAME_MISMATCH);
      goto out;
    }

  DEBUG ("Hostname matched");
  complete_verification (self);

 out:
  free_certificate_list_for_gnutls (list, n_list);
  free_certificate_list_for_gnutls (anchors, n_anchors);
}
static void
inf_gtk_certificate_manager_certificate_func(InfXmppConnection* connection,
                                             gnutls_session_t session,
                                             InfCertificateChain* chain,
                                             gpointer user_data)
{
  InfGtkCertificateManager* manager;
  InfGtkCertificateManagerPrivate* priv;

  InfGtkCertificateDialogFlags flags;
  gnutls_x509_crt_t presented_cert;
  gnutls_x509_crt_t known_cert;
  gchar* hostname;

  gboolean match_hostname;
  gboolean issuer_known;
  gnutls_x509_crt_t root_cert;

  int ret;
  unsigned int verify;
  GHashTable* table;
  gboolean cert_equal;
  time_t expiration_time;

  InfGtkCertificateManagerQuery* query;
  gchar* text;
  GtkWidget* vbox;
  GtkWidget* button;
  GtkWidget* image;
  GtkWidget* label;

  GError* error;

  manager = INF_GTK_CERTIFICATE_MANAGER(user_data);
  priv = INF_GTK_CERTIFICATE_MANAGER_PRIVATE(manager);

  g_object_get(G_OBJECT(connection), "remote-hostname", &hostname, NULL);
  presented_cert = inf_certificate_chain_get_own_certificate(chain);

  match_hostname = gnutls_x509_crt_check_hostname(presented_cert, hostname);

  /* First, validate the certificate */
  ret = gnutls_certificate_verify_peers2(session, &verify);
  error = NULL;

  if(ret != GNUTLS_E_SUCCESS)
    inf_gnutls_set_error(&error, ret);

  /* Remove the GNUTLS_CERT_ISSUER_NOT_KNOWN flag from the verification
   * result, and if the certificate is still invalid, then set an error. */
  if(error == NULL)
  {
    issuer_known = TRUE;
    if(verify & GNUTLS_CERT_SIGNER_NOT_FOUND)
    {
      issuer_known = FALSE;

      /* Re-validate the certificate for other failure reasons --
       * unfortunately the gnutls_certificate_verify_peers2() call
       * does not tell us whether the certificate is otherwise invalid
       * if a signer is not found already. */
      /* TODO: Here it would be good to use the verify flags from the
       * certificate credentials, but GnuTLS does not have API to
       * retrieve them. */
      root_cert = inf_certificate_chain_get_root_certificate(chain);

      ret = gnutls_x509_crt_list_verify(
        inf_certificate_chain_get_raw(chain),
        inf_certificate_chain_get_n_certificates(chain),
        &root_cert,
        1,
        NULL,
        0,
        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT,
        &verify
      );

      if(ret != GNUTLS_E_SUCCESS)
        inf_gnutls_set_error(&error, ret);
      else if(verify & GNUTLS_CERT_INVALID)
        inf_gnutls_certificate_verification_set_error(&error, verify);
    }
  }

  /* Look up the host in our database of pinned certificates if we could not
   * fully verify the certificate, i.e. if either the issuer is not known or
   * the hostname of the connection does not match the certificate. */
  table = NULL;
  if(error == NULL)
  {
    known_cert = NULL;
    if(!match_hostname || !issuer_known)
    {
      /* If we cannot load the known host file, then cancel the connection.
       * Otherwise it might happen that someone shows us a certificate that we
       * tell the user we don't know, if though actually for that host we expect
       * a different certificate. */
      table = inf_gtk_certificate_manager_ref_known_hosts(manager, &error);
      if(table != NULL)
        known_cert = g_hash_table_lookup(table, hostname);
    }
  }

  /* Next, configure the flags for the dialog to be shown based on the
   * verification result, and on whether the pinned certificate matches
   * the one presented by the host or not. */
  flags = 0;
  if(error == NULL)
  {
    if(known_cert != NULL)
    {
      cert_equal = inf_gtk_certificate_manager_compare_fingerprint(
        known_cert,
        presented_cert,
        &error
      );

      if(error == NULL && cert_equal == FALSE)
      {
        if(!match_hostname)
          flags |= INF_GTK_CERTIFICATE_DIALOG_CERT_HOSTNAME_MISMATCH;
        if(!issuer_known)
          flags |= INF_GTK_CERTIFICATE_DIALOG_CERT_ISSUER_NOT_KNOWN;

        flags |= INF_GTK_CERTIFICATE_DIALOG_CERT_UNEXPECTED;
        expiration_time = gnutls_x509_crt_get_expiration_time(known_cert);
        if(expiration_time != (time_t)(-1))
        {
          expiration_time -= INF_GTK_CERTIFICATE_MANAGER_EXPIRATION_TOLERANCE;
          if(time(NULL) > expiration_time)
          {
            flags |= INF_GTK_CERTIFICATE_DIALOG_CERT_OLD_EXPIRED;
          }
        }
      }
    }
    else
    {
      if(!match_hostname)
        flags |= INF_GTK_CERTIFICATE_DIALOG_CERT_HOSTNAME_MISMATCH;
      if(!issuer_known)
        flags |= INF_GTK_CERTIFICATE_DIALOG_CERT_ISSUER_NOT_KNOWN;
    }
  }

  /* Now proceed either by accepting the connection, rejecting it, or
   * bothering the user with an annoying dialog. */
  if(error == NULL)
  {
    if(flags == 0)
    {
      if(match_hostname && issuer_known)
      {
        /* Remove the pinned entry if we now have a valid certificate for
         * this host. */
        if(table != NULL && g_hash_table_remove(table, hostname) == TRUE)
        {
          inf_gtk_certificate_manager_write_known_hosts_with_warning(
            manager,
            table
          );
        }
      }

      inf_xmpp_connection_certificate_verify_continue(connection);
    }
    else
    {
      query = g_slice_new(InfGtkCertificateManagerQuery);
      query->manager = manager;
      query->known_hosts = table;
      query->connection = connection;
      query->dialog = inf_gtk_certificate_dialog_new(
        priv->parent_window,
        0,
        flags,
        hostname,
        chain
      );
      query->certificate_chain = chain;

      table = NULL;

      g_object_ref(query->connection);
      inf_certificate_chain_ref(chain);

      g_signal_connect(
        G_OBJECT(connection),
        "notify::status",
        G_CALLBACK(inf_gtk_certificate_manager_notify_status_cb),
        query
      );

      g_signal_connect(
        G_OBJECT(query->dialog),
        "response",
        G_CALLBACK(inf_gtk_certificate_manager_response_cb),
        query
      );

      image = gtk_image_new_from_stock(GTK_STOCK_CANCEL, GTK_ICON_SIZE_BUTTON);
      gtk_widget_show(image);

      button = gtk_dialog_add_button(
        GTK_DIALOG(query->dialog),
        _("_Cancel connection"),
        GTK_RESPONSE_REJECT
      );

      gtk_button_set_image(GTK_BUTTON(button), image);

      image = gtk_image_new_from_stock(GTK_STOCK_CONNECT, GTK_ICON_SIZE_BUTTON);
      gtk_widget_show(image);

      button = gtk_dialog_add_button(
        GTK_DIALOG(query->dialog),
        _("C_ontinue connection"),
        GTK_RESPONSE_ACCEPT
      );

      gtk_button_set_image(GTK_BUTTON(button), image);

      text = g_strdup_printf(
        _("Do you want to continue the connection to host \"%s\"? If you "
          "choose to continue, this certificate will be trusted in the "
          "future when connecting to this host."),
        hostname
      );

      label = gtk_label_new(text);
      gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
      gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
      gtk_label_set_width_chars(GTK_LABEL(label), 60);
      gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
      gtk_widget_show(label);
      g_free(text);

      vbox = gtk_dialog_get_content_area(GTK_DIALOG(query->dialog));
      gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);

      priv->queries = g_slist_prepend(priv->queries, query);
      gtk_window_present(GTK_WINDOW(query->dialog));
    }
  }
  else
  {
    inf_xmpp_connection_certificate_verify_cancel(connection, error);
    g_error_free(error);
  }

  if(table != NULL) g_hash_table_unref(table);
  g_free(hostname);
}
Пример #5
0
void
doit (void)
{
  int exit_val = 0;
  size_t i;
  int ret;

  /* The overloading of time() seems to work in linux (ELF?)
   * systems only. Disable it on windows.
   */
#ifdef _WIN32
  exit(77);
#endif

  ret = gnutls_global_init ();
  if (ret != 0)
    {
      fail ("%d: %s\n", ret, gnutls_strerror (ret));
      exit (EXIT_FAILURE);
    }

  gnutls_global_set_time_function (mytime);
  gnutls_global_set_log_function (tls_log_func);
  if (debug)
    gnutls_global_set_log_level (4711);

  for (i = 0; chains[i].chain; i++)
    {
      unsigned int verify_status;
      gnutls_x509_crt_t certs[4];
      gnutls_x509_crt_t ca;
      gnutls_datum_t tmp;
      size_t j;

      if (debug)
        printf ("Chain '%s' (%d)...\n", chains[i].name, (int) i);

      for (j = 0; chains[i].chain[j]; j++)
        {
          if (debug > 2)
            printf ("\tAdding certificate %d...", (int) j);

          ret = gnutls_x509_crt_init (&certs[j]);
          if (ret < 0)
            error (EXIT_FAILURE, 0, "gnutls_x509_crt_init[%d,%d]: %s",
                   (int) i, (int) j, gnutls_strerror (ret));

          tmp.data = (unsigned char *) chains[i].chain[j];
          tmp.size = strlen (chains[i].chain[j]);

          ret = gnutls_x509_crt_import (certs[j], &tmp, GNUTLS_X509_FMT_PEM);
          if (debug > 2)
            printf ("done\n");
          if (ret < 0)
            error (EXIT_FAILURE, 0, "gnutls_x509_crt_import[%d,%d]: %s",
                   (int) i, (int) j, gnutls_strerror (ret));

          gnutls_x509_crt_print (certs[j], GNUTLS_CRT_PRINT_ONELINE, &tmp);
          if (debug)
            printf ("\tCertificate %d: %.*s\n", (int) j, tmp.size, tmp.data);
          gnutls_free (tmp.data);
        }

      if (debug > 2)
        printf ("\tAdding CA certificate...");

      ret = gnutls_x509_crt_init (&ca);
      if (ret < 0)
        error (EXIT_FAILURE, 0, "gnutls_x509_crt_init: %s",
               gnutls_strerror (ret));

      tmp.data = (unsigned char *) *chains[i].ca;
      tmp.size = strlen (*chains[i].ca);

      ret = gnutls_x509_crt_import (ca, &tmp, GNUTLS_X509_FMT_PEM);
      if (ret < 0)
        error (EXIT_FAILURE, 0, "gnutls_x509_crt_import: %s",
               gnutls_strerror (ret));

      if (debug > 2)
        printf ("done\n");

      gnutls_x509_crt_print (ca, GNUTLS_CRT_PRINT_ONELINE, &tmp);
      if (debug)
        printf ("\tCA Certificate: %.*s\n", tmp.size, tmp.data);
      gnutls_free (tmp.data);

      if (debug)
        printf ("\tVerifying...");

      ret = gnutls_x509_crt_list_verify (certs, j,
                                         &ca, 1, NULL, 0,
                                         chains[i].verify_flags,
                                         &verify_status);
      if (ret < 0)
        error (EXIT_FAILURE, 0, "gnutls_x509_crt_list_verify[%d,%d]: %s",
               (int) i, (int) j, gnutls_strerror (ret));

      if (verify_status != chains[i].expected_verify_result)
        {
          fail ("chain[%s]: verify_status: %d expected: %d\n", chains[i].name,
                verify_status, chains[i].expected_verify_result);

#if 0
          j = 0;
          do
            {
              fprintf (stderr, "%s\n", chains[i].chain[j]);
            }
          while (chains[i].chain[++j] != NULL);
#endif

          if (!debug)
            exit (1);
        }
      else if (debug)
        printf ("done\n");
      if (debug)
        printf ("\tCleanup...");

      gnutls_x509_crt_deinit (ca);
      for (j = 0; chains[i].chain[j]; j++)
        gnutls_x509_crt_deinit (certs[j]);

      if (debug)
        printf ("done\n\n\n");
    }

  gnutls_global_deinit ();

  if (debug)
    printf ("Exit status...%d\n", exit_val);

  exit (exit_val);
}
Пример #6
0
/*-
  * gnutls_x509_verify_certificate - This function verifies given certificate list
  * @cert_list: is the certificate list to be verified
  * @cert_list_length: holds the number of certificate in cert_list
  * @CA_list: is the CA list which will be used in verification
  * @CA_list_length: holds the number of CA certificate in CA_list
  * @CRL_list: not used
  * @CRL_list_length: not used
  *
  * This function will try to verify the given certificate list and return its status (TRUSTED, EXPIRED etc.). 
  * The return value (status) should be one or more of the gnutls_certificate_status_t 
  * enumerated elements bitwise or'd. Note that expiration and activation dates are not checked 
  * by this function, you should check them using the appropriate functions.
  *
  * This function understands the basicConstraints (2.5.29.19) PKIX extension.
  * This means that only a certificate authority can sign a certificate.
  *
  * However you must also check the peer's name in order to check if the verified certificate belongs to the 
  * actual peer. 
  *
  * The return value (status) should be one or more of the gnutls_certificate_status_t 
  * enumerated elements bitwise or'd.
  *
  * GNUTLS_CERT_INVALID: the peer's certificate is not valid.
  *
  * GNUTLS_CERT_REVOKED: the certificate has been revoked.
  *
  * A negative error code is returned in case of an error.
  * GNUTLS_E_NO_CERTIFICATE_FOUND is returned to indicate that
  * no certificate was sent by the peer.
  *  
  *
  -*/
int
gnutls_x509_verify_certificate (const gnutls_datum_t * cert_list,
				int cert_list_length,
				const gnutls_datum_t * CA_list,
				int CA_list_length,
				const gnutls_datum_t * CRL_list,
				int CRL_list_length)
{
  unsigned int verify;
  gnutls_x509_crt_t *peer_certificate_list = NULL;
  gnutls_x509_crt_t *ca_certificate_list = NULL;
  gnutls_x509_crl_t *crl_list = NULL;
  int peer_certificate_list_size = 0, i, x, ret;
  int ca_certificate_list_size = 0, crl_list_size = 0;

  if (cert_list == NULL || cert_list_length == 0)
    return GNUTLS_E_NO_CERTIFICATE_FOUND;

  /* generate a list of gnutls_certs based on the auth info
   * raw certs.
   */
  peer_certificate_list_size = cert_list_length;
  peer_certificate_list =
    gnutls_calloc (1,
		   peer_certificate_list_size * sizeof (gnutls_x509_crt_t));
  if (peer_certificate_list == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto cleanup;
    }

  ca_certificate_list_size = CA_list_length;
  ca_certificate_list =
    gnutls_calloc (1, ca_certificate_list_size * sizeof (gnutls_x509_crt_t));
  if (ca_certificate_list == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto cleanup;
    }

  /* allocate memory for CRL
   */
  crl_list_size = CRL_list_length;
  crl_list = gnutls_calloc (1, crl_list_size * sizeof (gnutls_x509_crl_t));
  if (crl_list == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto cleanup;
    }

  /* convert certA_list to gnutls_cert* list
   */
  for (i = 0; i < peer_certificate_list_size; i++)
    {
      ret = gnutls_x509_crt_init (&peer_certificate_list[i]);
      if (ret < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}

      ret =
	gnutls_x509_crt_import (peer_certificate_list[i],
				&cert_list[i], GNUTLS_X509_FMT_DER);
      if (ret < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
    }

  /* convert CA_list to gnutls_x509_cert* list
   */
  for (i = 0; i < ca_certificate_list_size; i++)
    {
      ret = gnutls_x509_crt_init (&ca_certificate_list[i]);
      if (ret < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}

      ret =
	gnutls_x509_crt_import (ca_certificate_list[i],
				&CA_list[i], GNUTLS_X509_FMT_DER);
      if (ret < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
    }

#ifdef ENABLE_PKI
  /* convert CRL_list to gnutls_x509_crl* list
   */
  for (i = 0; i < crl_list_size; i++)
    {
      ret = gnutls_x509_crl_init (&crl_list[i]);
      if (ret < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}

      ret =
	gnutls_x509_crl_import (crl_list[i],
				&CRL_list[i], GNUTLS_X509_FMT_DER);
      if (ret < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
    }
#endif

  /* Verify certificate 
   */
  ret =
    gnutls_x509_crt_list_verify (peer_certificate_list,
				 peer_certificate_list_size,
				 ca_certificate_list,
				 ca_certificate_list_size, crl_list,
				 crl_list_size, 0, &verify);

  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  ret = verify;

cleanup:

  if (peer_certificate_list != NULL)
    for (x = 0; x < peer_certificate_list_size; x++)
      {
	if (peer_certificate_list[x] != NULL)
	  gnutls_x509_crt_deinit (peer_certificate_list[x]);
      }

  if (ca_certificate_list != NULL)
    for (x = 0; x < ca_certificate_list_size; x++)
      {
	if (ca_certificate_list[x] != NULL)
	  gnutls_x509_crt_deinit (ca_certificate_list[x]);
      }
#ifdef ENABLE_PKI
  if (crl_list != NULL)
    for (x = 0; x < crl_list_size; x++)
      {
	if (crl_list[x] != NULL)
	  gnutls_x509_crl_deinit (crl_list[x]);
      }

  gnutls_free (crl_list);
#endif

  gnutls_free (ca_certificate_list);
  gnutls_free (peer_certificate_list);

  return ret;
}
Пример #7
0
void
doit (void)
{
  int exit_val = 0;
  size_t i;
  int ret;

  ret = gnutls_global_init ();
  if (ret != 0)
    {
      fail ("%d: %s\n", ret, gnutls_strerror (ret));
      exit (EXIT_FAILURE);
    }

  gnutls_global_set_log_function (tls_log_func);
  if (debug)
    gnutls_global_set_log_level (4711);

  for (i = 0; chains[i].chain; i++)
    {
      unsigned int verify_status;
      gnutls_x509_crt_t certs[4];
      gnutls_x509_crt_t ca;
      gnutls_datum_t tmp;
      size_t j;

      if (debug)
	printf ("Chain '%s' (%d)...\n", chains[i].name, (int) i);

      for (j = 0; chains[i].chain[j]; j++)
	{
	  if (debug)
	    printf ("\tAdding certificate %d...", (int) j);

	  ret = gnutls_x509_crt_init (&certs[j]);
	  if (ret < 0)
	    error (EXIT_FAILURE, 0, "gnutls_x509_crt_init[%d,%d]: %s",
		   (int) i, (int) j, gnutls_strerror (ret));

	  tmp.data = (char *) chains[i].chain[j];
	  tmp.size = strlen (chains[i].chain[j]);

	  ret = gnutls_x509_crt_import (certs[j], &tmp, GNUTLS_X509_FMT_PEM);
	  if (debug)
	    printf ("done\n");
	  if (ret < 0)
	    error (EXIT_FAILURE, 0, "gnutls_x509_crt_import[%d,%d]: %s",
		   (int) i, (int) j, gnutls_strerror (ret));

	  gnutls_x509_crt_print (certs[j], GNUTLS_CRT_PRINT_ONELINE, &tmp);
	  if (debug)
	    printf ("\tCertificate %d: %.*s\n", (int) j, tmp.size, tmp.data);
	  gnutls_free (tmp.data);
	}

      if (debug)
	printf ("\tAdding CA certificate...");

      ret = gnutls_x509_crt_init (&ca);
      if (ret < 0)
	error (EXIT_FAILURE, 0, "gnutls_x509_crt_init: %s",
	       gnutls_strerror (ret));

      tmp.data = (char *) *chains[i].ca;
      tmp.size = strlen (*chains[i].ca);

      ret = gnutls_x509_crt_import (ca, &tmp, GNUTLS_X509_FMT_PEM);
      if (ret < 0)
	error (EXIT_FAILURE, 0, "gnutls_x509_crt_import: %s",
	       gnutls_strerror (ret));

      if (debug)
	printf ("done\n");

      gnutls_x509_crt_print (ca, GNUTLS_CRT_PRINT_ONELINE, &tmp);
      if (debug)
	printf ("\tCA Certificate: %.*s\n", tmp.size, tmp.data);
      gnutls_free (tmp.data);

      if (debug)
	printf ("\tVerifying...");

      ret = gnutls_x509_crt_list_verify (certs, j,
					 &ca, 1, NULL, 0,
					 chains[i].verify_flags,
					 &verify_status);
      if (ret < 0)
	error (EXIT_FAILURE, 0, "gnutls_x509_crt_list_verify[%d,%d]: %s",
	       (int) i, (int) j, gnutls_strerror (ret));

      if (verify_status != chains[i].expected_verify_result)
	{
	  fail ("verify_status: %d expected: %d",
		verify_status, chains[i].expected_verify_result);

	  if (!debug)
	    exit (1);
	}
      else if (debug)
	printf ("done\n");
      if (debug)
	printf ("\tCleanup...");

      gnutls_x509_crt_deinit (ca);
      for (j = 0; chains[i].chain[j]; j++)
	gnutls_x509_crt_deinit (certs[j]);

      if (debug)
	printf ("done\n");
    }

  gnutls_global_deinit ();

  if (debug)
    printf ("Exit status...%d\n", exit_val);

  exit (exit_val);
}
Пример #8
0
/*-
 * _gnutls_x509_cert_verify_peers - return the peer's certificate status
 * @session: is a gnutls session
 *
 * This function will try to verify the peer's certificate and return its status (TRUSTED, REVOKED etc.).
 * The return value (status) should be one of the gnutls_certificate_status_t enumerated elements.
 * However you must also check the peer's name in order to check if the verified certificate belongs to the
 * actual peer. Returns a negative error code in case of an error, or GNUTLS_E_NO_CERTIFICATE_FOUND if no certificate was sent.
 -*/
int
_gnutls_x509_cert_verify_peers (gnutls_session_t session,
				unsigned int *status)
{
  cert_auth_info_t info;
  gnutls_certificate_credentials_t cred;
  gnutls_x509_crt_t *peer_certificate_list;
  int peer_certificate_list_size, i, x, ret;

  CHECK_AUTH (GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);

  info = _gnutls_get_auth_info (session);
  if (info == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  cred = (gnutls_certificate_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
  if (cred == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  if (info->raw_certificate_list == NULL || info->ncerts == 0)
    return GNUTLS_E_NO_CERTIFICATE_FOUND;

  if (info->ncerts > cred->verify_depth && cred->verify_depth > 0)
    {
      gnutls_assert ();
      return GNUTLS_E_CONSTRAINT_ERROR;
    }

  /* generate a list of gnutls_certs based on the auth info
   * raw certs.
   */
  peer_certificate_list_size = info->ncerts;
  peer_certificate_list =
    gnutls_calloc (peer_certificate_list_size, sizeof (gnutls_x509_crt_t));
  if (peer_certificate_list == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  for (i = 0; i < peer_certificate_list_size; i++)
    {
      ret = gnutls_x509_crt_init (&peer_certificate_list[i]);
      if (ret < 0)
	{
	  gnutls_assert ();
	  CLEAR_CERTS;
	  return ret;
	}

      ret =
	gnutls_x509_crt_import (peer_certificate_list[i],
				&info->raw_certificate_list[i],
				GNUTLS_X509_FMT_DER);
      if (ret < 0)
	{
	  gnutls_assert ();
	  CLEAR_CERTS;
	  return ret;
	}


      if (ret < 0)
	{
	  gnutls_assert ();
	  CLEAR_CERTS;
	  return ret;
	}

      ret = check_bits (peer_certificate_list[i], cred->verify_bits);
      if (ret < 0)
	{
	  gnutls_assert ();
	  CLEAR_CERTS;
	  return ret;
	}

    }

  /* Verify certificate 
   */

  ret = gnutls_x509_crt_list_verify (peer_certificate_list,
				     peer_certificate_list_size,
				     cred->x509_ca_list, cred->x509_ncas,
				     cred->x509_crl_list, cred->x509_ncrls,
				     cred->verify_flags | session->internals.
				     priorities.additional_verify_flags,
				     status);

  CLEAR_CERTS;

  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return 0;
}
Пример #9
0
int
main (int argc, char *argv[])
{
  int ret;
  gnutls_x509_crt_t certs[3];
  gnutls_x509_crt_t ca;
  gnutls_x509_crt_t self_cert;
  gnutls_datum_t tmp;
  size_t i;
  unsigned int verify_status;

  ret = gnutls_global_init ();
  if (ret != 0)
    {
      printf ("%d: %s\n", ret, gnutls_strerror (ret));
      return EXIT_FAILURE;
    }

  for (i = 0; i < CHAIN_LENGTH; i++)
    {
      ret = gnutls_x509_crt_init (&certs[i]);
      if (ret < 0)
	error (EXIT_FAILURE, 0, "gnutls_x509_crt_init[%d]: %s", (int) i,
	       gnutls_strerror (ret));

      tmp.data = (char *) pem_certs[i];
      tmp.size = strlen (pem_certs[i]);

      ret = gnutls_x509_crt_import (certs[i], &tmp, GNUTLS_X509_FMT_PEM);
      if (ret < 0)
	error (EXIT_FAILURE, 0, "gnutls_x509_crt_import[%d]: %s", (int) i,
	       gnutls_strerror (ret));
    }

  ret = gnutls_x509_crt_init (&ca);
  if (ret < 0)
    error (EXIT_FAILURE, 0, "gnutls_x509_crt_init: %s",
	   gnutls_strerror (ret));

  tmp.data = (char *) pem_ca;
  tmp.size = strlen (pem_ca);

  ret = gnutls_x509_crt_import (ca, &tmp, GNUTLS_X509_FMT_PEM);
  if (ret < 0)
    error (EXIT_FAILURE, 0, "gnutls_x509_crt_import: %s",
	   gnutls_strerror (ret));

  ret = gnutls_x509_crt_list_verify (certs, CHAIN_LENGTH,
				     &ca, 1,
				     NULL, 0,
				     GNUTLS_VERIFY_DISABLE_TIME_CHECKS,
				     &verify_status);
  if (ret < 0)
    error (EXIT_FAILURE, 0, "gnutls_x509_crt_list_verify[%d]: %s", (int) i,
	   gnutls_strerror (ret));

  if (verify_status != (GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID))
    error (EXIT_FAILURE, 0, "verify_status: %d", verify_status);

  gnutls_x509_crt_deinit (ca);
  for (i = 0; i < CHAIN_LENGTH; i++)
    gnutls_x509_crt_deinit (certs[i]);

  /* Also test chain length of 1, since the initial patch to solve the
     problem caused a crash in this situation. */

  ret = gnutls_x509_crt_init (&self_cert);
  if (ret < 0)
    error (EXIT_FAILURE, 0, "gnutls_x509_crt_init: %s",
	   gnutls_strerror (ret));

  tmp.data = (char *) pem_self_cert;
  tmp.size = strlen (pem_self_cert);

  ret = gnutls_x509_crt_import (self_cert, &tmp, GNUTLS_X509_FMT_PEM);
  if (ret < 0)
    error (EXIT_FAILURE, 0, "gnutls_x509_crt_import: %s",
	   gnutls_strerror (ret));

  ret = gnutls_x509_crt_list_verify (&self_cert, 1,
				     &self_cert, 1,
				     NULL, 0,
				     GNUTLS_VERIFY_DISABLE_TIME_CHECKS,
				     &verify_status);
  if (ret < 0)
    error (EXIT_FAILURE, 0, "gnutls_x509_crt_list_verify[%d]: %s", (int) i,
	   gnutls_strerror (ret));

  if (verify_status != 0)
    error (EXIT_FAILURE, 0, "verify_status: %d", verify_status);

  gnutls_x509_crt_deinit (self_cert);

  gnutls_global_deinit ();

  return 0;
}