telepathy-glib: TpTLSCertificate: track the signalled rejection reason(s)

Guillaume Desmottes gdesmott at kemper.freedesktop.org
Wed May 9 03:15:57 PDT 2012


Module: telepathy-glib
Branch: master
Commit: c39eff9d8fdbb0de2235440d159d2d6923d0f674
URL:    http://cgit.freedesktop.org/telepathy/telepathy-glib/commit/?id=c39eff9d8fdbb0de2235440d159d2d6923d0f674

Author: Simon McVittie <simon.mcvittie at collabora.co.uk>
Date:   Wed Dec 15 13:00:00 2010 +0000

TpTLSCertificate: track the signalled rejection reason(s)

---

 docs/reference/telepathy-glib-sections.txt |    2 +
 telepathy-glib/tls-certificate.c           |  162 +++++++++++++++++++++++++++-
 telepathy-glib/tls-certificate.h           |   10 ++
 3 files changed, 173 insertions(+), 1 deletions(-)

diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt
index 69cdec9..d5b4b6a 100644
--- a/docs/reference/telepathy-glib-sections.txt
+++ b/docs/reference/telepathy-glib-sections.txt
@@ -7331,6 +7331,8 @@ TpTLSCertificate
 tp_tls_certificate_init_known_interfaces
 tp_tls_certificate_new
 TP_TLS_CERTIFICATE_FEATURE_CORE
+tp_tls_certificate_get_rejection
+tp_tls_certificate_get_nth_rejection
 tp_tls_certificate_accept_async
 tp_tls_certificate_accept_finish
 tp_tls_certificate_reject_async
diff --git a/telepathy-glib/tls-certificate.c b/telepathy-glib/tls-certificate.c
index 1041baa..901a097 100644
--- a/telepathy-glib/tls-certificate.c
+++ b/telepathy-glib/tls-certificate.c
@@ -81,6 +81,8 @@ struct _TpTLSCertificatePrivate {
   gchar *cert_type;
   GPtrArray *cert_data;
   TpTLSCertificateState state;
+  /* array of SignalledRejection */
+  GArray *rejections;
 };
 
 G_DEFINE_TYPE (TpTLSCertificate, tp_tls_certificate,
@@ -113,11 +115,40 @@ tp_tls_certificate_get_feature_quark_core (void)
   return g_quark_from_static_string ("tp-tls-certificate-feature-core");
 }
 
+typedef struct {
+    GError *error /* NULL-initialized later */ ;
+    TpTLSCertificateRejectReason reason;
+    gchar *dbus_error;
+    GHashTable *details;
+} SignalledRejection;
+
+static void
+tp_tls_certificate_clear_rejections (TpTLSCertificate *self)
+{
+  if (self->priv->rejections != NULL)
+    {
+      guint i;
+
+      for (i = 0; i < self->priv->rejections->len; i++)
+        {
+          SignalledRejection *sr = &g_array_index (self->priv->rejections,
+              SignalledRejection, i);
+
+          g_clear_error (&sr->error);
+          tp_clear_pointer (&sr->dbus_error, g_free);
+          tp_clear_pointer (&sr->details, g_hash_table_unref);
+        }
+    }
+
+  tp_clear_pointer (&self->priv->rejections, g_array_unref);
+}
+
 static void
 tp_tls_certificate_accepted_cb (TpTLSCertificate *self,
     gpointer unused G_GNUC_UNUSED,
     GObject *unused_object G_GNUC_UNUSED)
 {
+  tp_tls_certificate_clear_rejections (self);
   self->priv->state = TP_TLS_CERTIFICATE_STATE_ACCEPTED;
   g_object_notify ((GObject *) self, "state");
 }
@@ -129,6 +160,56 @@ tp_tls_certificate_rejected_cb (TpTLSCertificate *self,
     GObject *unused_object G_GNUC_UNUSED)
 {
   self->priv->state = TP_TLS_CERTIFICATE_STATE_REJECTED;
+
+  tp_tls_certificate_clear_rejections (self);
+
+  if (rejections == NULL || rejections->len == 0)
+    {
+      SignalledRejection sr = {
+            g_error_new_literal (TP_ERROR, TP_ERROR_CERT_INVALID,
+                "Rejected, no reason given"),
+            TP_TLS_CERTIFICATE_REJECT_REASON_UNKNOWN,
+            g_strdup (TP_ERROR_STR_CERT_INVALID),
+            tp_asv_new (NULL, NULL) };
+
+      self->priv->rejections = g_array_sized_new (FALSE, FALSE,
+          sizeof (SignalledRejection), 1);
+      g_array_append_val (self->priv->rejections, sr);
+    }
+  else
+    {
+      guint i;
+
+      self->priv->rejections = g_array_sized_new (FALSE, FALSE,
+          sizeof (SignalledRejection), rejections->len);
+
+      for (i = 0; i < rejections->len; i++)
+        {
+          SignalledRejection sr = { NULL };
+          GValueArray *va = g_ptr_array_index (rejections, i);
+          const gchar *error_name;
+          const GHashTable *details;
+
+          tp_value_array_unpack (va, 3,
+              &sr.reason,
+              &error_name,
+              &details);
+
+          tp_proxy_dbus_error_to_gerror (self, error_name,
+              tp_asv_get_string (details, "debug-message"), &sr.error);
+
+          sr.details = g_hash_table_new_full (g_str_hash, g_str_equal,
+              g_free, (GDestroyNotify) tp_g_value_slice_free);
+          tp_g_hash_table_update (sr.details, (GHashTable *) details,
+              (GBoxedCopyFunc) g_strdup,
+              (GBoxedCopyFunc) tp_g_value_slice_dup);
+
+          sr.dbus_error = g_strdup (error_name);
+
+          g_array_append_val (self->priv->rejections, sr);
+        }
+    }
+
   g_object_notify ((GObject *) self, "state");
 }
 
@@ -248,6 +329,7 @@ tp_tls_certificate_finalize (GObject *object)
 
   DEBUG ("%p", object);
 
+  tp_tls_certificate_clear_rejections (self);
   g_free (priv->cert_type);
   tp_clear_boxed (TP_ARRAY_TYPE_UCHAR_ARRAY_LIST, &priv->cert_data);
 
@@ -624,7 +706,7 @@ tp_tls_certificate_reject_async (TpTLSCertificate *self,
 
   DEBUG ("Rejecting TLS certificate with reason %u", reason);
 
-  rejections = build_rejections_array (reason, details);
+  rejections = build_rejections_array (reason, dbus_error, details);
   reject_result = g_simple_async_result_new (G_OBJECT (self),
       callback, user_data, tp_tls_certificate_reject_async);
 
@@ -685,3 +767,81 @@ tp_tls_certificate_init_known_interfaces (void)
       g_once_init_leave (&once, 1);
     }
 }
+
+/**
+ * tp_tls_certificate_get_rejection:
+ * @self: a TLS certificate
+ * @reason: (out) (allow-none): optionally used to return the reason code
+ * @dbus_error: (out) (type utf8) (allow-none) (transfer none): optionally
+ *  used to return the D-Bus error name
+ * @details: (out) (allow-none) (transfer none) (element-type utf8 GObject.Value):
+ *  optionally used to return a map from string to #GValue, which must not be
+ *  modified or destroyed by the caller
+ *
+ * If this certificate has been rejected, return a #GError (likely to be in
+ * the %TP_ERROR domain) indicating the first rejection reason (by convention,
+ * the most important).
+ *
+ * If you want to list all the things that are wrong with the certificate
+ * (for instance, it might be self-signed and also have expired)
+ * you can call tp_tls_certificate_get_nth_rejection(), increasing @n until
+ * it returns %NULL.
+ *
+ * Returns: (transfer none) (allow-none): a #GError, or %NULL
+ */
+const GError *
+tp_tls_certificate_get_rejection (TpTLSCertificate *self,
+    TpTLSCertificateRejectReason *reason,
+    const gchar **dbus_error,
+    const GHashTable **details)
+{
+  return tp_tls_certificate_get_nth_rejection (self, 0, reason, dbus_error,
+      details);
+}
+
+/**
+ * tp_tls_certificate_get_nth_rejection:
+ * @self: a TLS certificate
+ * @n: the rejection reason to return; if 0, return the same thing as
+ *  tp_tls_certificate_get_detailed_rejection()
+ * @reason: (out) (allow-none): optionally used to return the reason code
+ * @dbus_error: (out) (type utf8) (allow-none) (transfer none): optionally
+ *  used to return the D-Bus error name
+ * @details: (out) (allow-none) (transfer none) (element-type utf8 GObject.Value):
+ *  optionally used to return a map from string to #GValue, which must not be
+ *  modified or destroyed by the caller
+ *
+ * If this certificate has been rejected and @n is less than the number of
+ * rejection reasons, return a #GError representing the @n<!---->th rejection
+ * reason (starting from 0), with additional information returned via the
+ * 'out' parameters.
+ *
+ * With @n == 0 this is equivalent to tp_tls_certificate_get_rejection().
+ *
+ * Returns: (transfer none) (allow-none): a #GError, or %NULL
+ */
+const GError *
+tp_tls_certificate_get_nth_rejection (TpTLSCertificate *self,
+    guint n,
+    TpTLSCertificateRejectReason *reason,
+    const gchar **dbus_error,
+    const GHashTable **details)
+{
+  const SignalledRejection *rej;
+
+  if (self->priv->rejections == NULL || n >= self->priv->rejections->len)
+    return NULL;
+
+  rej = &g_array_index (self->priv->rejections, SignalledRejection, n);
+
+  if (reason != NULL)
+    *reason = rej->reason;
+
+  if (dbus_error != NULL)
+    *dbus_error = rej->dbus_error;
+
+  if (details != NULL)
+    *details = rej->details;
+
+  return rej->error;
+}
diff --git a/telepathy-glib/tls-certificate.h b/telepathy-glib/tls-certificate.h
index 300a9ae..8b97e88 100644
--- a/telepathy-glib/tls-certificate.h
+++ b/telepathy-glib/tls-certificate.h
@@ -76,6 +76,16 @@ TpTLSCertificate *tp_tls_certificate_new (TpProxy *conn_or_chan,
     const gchar *object_path,
     GError **error);
 
+const GError *tp_tls_certificate_get_rejection (TpTLSCertificate *self,
+    TpTLSCertificateRejectReason *reason,
+    const gchar **dbus_error,
+    const GHashTable **details);
+const GError *tp_tls_certificate_get_nth_rejection (TpTLSCertificate *self,
+    guint n,
+    TpTLSCertificateRejectReason *reason,
+    const gchar **dbus_error,
+    const GHashTable **details);
+
 void tp_tls_certificate_accept_async (TpTLSCertificate *self,
     GAsyncReadyCallback callback,
     gpointer user_data);



More information about the telepathy-commits mailing list