diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2010-12-15 13:00:00 +0000 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2012-05-09 12:14:09 +0200 |
commit | c39eff9d8fdbb0de2235440d159d2d6923d0f674 (patch) | |
tree | 248f307592423147eb19aefddaec47327c6620e2 | |
parent | 43978342cf1925fac3eca5cb2e4d235334228a76 (diff) |
TpTLSCertificate: track the signalled rejection reason(s)
-rw-r--r-- | docs/reference/telepathy-glib-sections.txt | 2 | ||||
-rw-r--r-- | telepathy-glib/tls-certificate.c | 162 | ||||
-rw-r--r-- | 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 69cdec90a..d5b4b6a52 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 1041baa0d..901a097a1 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 300a9aea3..8b97e884a 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); |