~ubuntu-branches/ubuntu/trusty/telepathy-idle/trusty

« back to all changes in this revision

Viewing changes to src/tls-certificate.c

  • Committer: Package Import Robot
  • Author(s): Simon McVittie
  • Date: 2013-05-01 15:52:26 UTC
  • mfrom: (1.3.6)
  • Revision ID: package-import@ubuntu.com-20130501155226-ttpmql3jetet34iu
Tags: 0.1.16-1
* New upstream release
  - adds support for interactive TLS certificate verification
    (Closes: #706270)
* Add a patch to avoid use of a telepathy-glib 0.20 header, to make
  this easy to backport to wheezy

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * tls-certificate.c - Source for IdleTLSCertificate
 
3
 * Copyright (C) 2010 Collabora Ltd.
 
4
 * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Lesser General Public
 
8
 * License as published by the Free Software Foundation; either
 
9
 * version 2.1 of the License, or (at your option) any later version.
 
10
 *
 
11
 * This library is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * Lesser General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General Public
 
17
 * License along with this library; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
#include "tls-certificate.h"
 
23
 
 
24
#include <telepathy-glib/telepathy-glib.h>
 
25
 
 
26
#if TP_MAJOR_VERSION > 0 || TP_MINOR_VERSION >= 20
 
27
#   include <telepathy-glib/telepathy-glib-dbus.h>
 
28
#else
 
29
#   include <telepathy-glib/gtypes.h>
 
30
#   include <telepathy-glib/interfaces.h>
 
31
#   include <telepathy-glib/svc-tls.h>
 
32
#endif
 
33
 
 
34
#define IDLE_DEBUG_FLAG IDLE_DEBUG_TLS
 
35
#include "idle-debug.h"
 
36
 
 
37
static void
 
38
tls_certificate_iface_init (gpointer g_iface, gpointer iface_data);
 
39
 
 
40
G_DEFINE_TYPE_WITH_CODE (IdleTLSCertificate,
 
41
    idle_tls_certificate,
 
42
    G_TYPE_OBJECT,
 
43
    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_AUTHENTICATION_TLS_CERTIFICATE,
 
44
        tls_certificate_iface_init);
 
45
    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
 
46
        tp_dbus_properties_mixin_iface_init);)
 
47
 
 
48
struct _IdleTLSCertificatePrivate {
 
49
  gchar *object_path;
 
50
 
 
51
  gchar *cert_type;
 
52
  TpTLSCertificateState cert_state;
 
53
 
 
54
  GPtrArray *rejections;
 
55
  GPtrArray *cert_data;
 
56
 
 
57
  TpDBusDaemon *daemon;
 
58
 
 
59
  gboolean dispose_has_run;
 
60
};
 
61
 
 
62
enum {
 
63
  PROP_OBJECT_PATH = 1,
 
64
  PROP_STATE,
 
65
  PROP_REJECTIONS,
 
66
  PROP_CERTIFICATE_TYPE,
 
67
  PROP_CERTIFICATE_CHAIN_DATA,
 
68
 
 
69
  /* not exported */
 
70
  PROP_DBUS_DAEMON,
 
71
 
 
72
  NUM_PROPERTIES
 
73
};
 
74
 
 
75
static void
 
76
idle_tls_certificate_get_property (GObject *object,
 
77
    guint property_id,
 
78
    GValue *value,
 
79
    GParamSpec *pspec)
 
80
{
 
81
  IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (object);
 
82
 
 
83
  switch (property_id)
 
84
    {
 
85
    case PROP_OBJECT_PATH:
 
86
      g_value_set_string (value, self->priv->object_path);
 
87
      break;
 
88
    case PROP_STATE:
 
89
      g_value_set_uint (value, self->priv->cert_state);
 
90
      break;
 
91
    case PROP_REJECTIONS:
 
92
      g_value_set_boxed (value, self->priv->rejections);
 
93
      break;
 
94
    case PROP_CERTIFICATE_TYPE:
 
95
      g_value_set_string (value, self->priv->cert_type);
 
96
      break;
 
97
    case PROP_CERTIFICATE_CHAIN_DATA:
 
98
      g_value_set_boxed (value, self->priv->cert_data);
 
99
      break;
 
100
    default:
 
101
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
102
      break;
 
103
  }
 
104
}
 
105
 
 
106
static void
 
107
idle_tls_certificate_set_property (GObject *object,
 
108
    guint property_id,
 
109
    const GValue *value,
 
110
    GParamSpec *pspec)
 
111
{
 
112
  IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (object);
 
113
 
 
114
  switch (property_id)
 
115
    {
 
116
    case PROP_OBJECT_PATH:
 
117
      self->priv->object_path = g_value_dup_string (value);
 
118
      break;
 
119
    case PROP_CERTIFICATE_TYPE:
 
120
      self->priv->cert_type = g_value_dup_string (value);
 
121
      break;
 
122
    case PROP_CERTIFICATE_CHAIN_DATA:
 
123
      self->priv->cert_data = g_value_dup_boxed (value);
 
124
      break;
 
125
    case PROP_DBUS_DAEMON:
 
126
      self->priv->daemon = g_value_dup_object (value);
 
127
      break;
 
128
    default:
 
129
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, value);
 
130
      break;
 
131
    }
 
132
}
 
133
 
 
134
static void
 
135
idle_tls_certificate_finalize (GObject *object)
 
136
{
 
137
  IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (object);
 
138
 
 
139
  tp_clear_boxed (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST,
 
140
      &self->priv->rejections);
 
141
 
 
142
  g_free (self->priv->object_path);
 
143
  g_free (self->priv->cert_type);
 
144
  g_ptr_array_unref (self->priv->cert_data);
 
145
 
 
146
  G_OBJECT_CLASS (idle_tls_certificate_parent_class)->finalize (object);
 
147
}
 
148
 
 
149
static void
 
150
idle_tls_certificate_dispose (GObject *object)
 
151
{
 
152
  IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (object);
 
153
 
 
154
  if (self->priv->dispose_has_run)
 
155
    return;
 
156
 
 
157
  self->priv->dispose_has_run = TRUE;
 
158
 
 
159
  tp_clear_object (&self->priv->daemon);
 
160
 
 
161
  G_OBJECT_CLASS (idle_tls_certificate_parent_class)->dispose (object);
 
162
}
 
163
 
 
164
static void
 
165
idle_tls_certificate_constructed (GObject *object)
 
166
{
 
167
  IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (object);
 
168
  void (*chain_up) (GObject *) =
 
169
    G_OBJECT_CLASS (idle_tls_certificate_parent_class)->constructed;
 
170
 
 
171
  if (chain_up != NULL)
 
172
    chain_up (object);
 
173
 
 
174
  /* register the certificate on the bus */
 
175
  tp_dbus_daemon_register_object (self->priv->daemon,
 
176
      self->priv->object_path, self);
 
177
}
 
178
 
 
179
static void
 
180
idle_tls_certificate_init (IdleTLSCertificate *self)
 
181
{
 
182
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
 
183
      IDLE_TYPE_TLS_CERTIFICATE, IdleTLSCertificatePrivate);
 
184
  self->priv->rejections = g_ptr_array_new ();
 
185
}
 
186
 
 
187
static void
 
188
idle_tls_certificate_class_init (IdleTLSCertificateClass *klass)
 
189
{
 
190
  static TpDBusPropertiesMixinPropImpl object_props[] = {
 
191
    { "State", "state", NULL },
 
192
    { "Rejections", "rejections", NULL },
 
193
    { "CertificateType", "certificate-type", NULL },
 
194
    { "CertificateChainData", "certificate-chain-data", NULL },
 
195
    { NULL }
 
196
  };
 
197
  static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
 
198
    { TP_IFACE_AUTHENTICATION_TLS_CERTIFICATE,
 
199
      tp_dbus_properties_mixin_getter_gobject_properties,
 
200
      NULL,
 
201
      object_props,
 
202
    },
 
203
    { NULL }
 
204
  };
 
205
  GObjectClass *oclass = G_OBJECT_CLASS (klass);
 
206
  GParamSpec *pspec;
 
207
 
 
208
  g_type_class_add_private (klass, sizeof (IdleTLSCertificatePrivate));
 
209
 
 
210
  oclass->finalize = idle_tls_certificate_finalize;
 
211
  oclass->dispose = idle_tls_certificate_dispose;
 
212
  oclass->set_property = idle_tls_certificate_set_property;
 
213
  oclass->get_property = idle_tls_certificate_get_property;
 
214
  oclass->constructed = idle_tls_certificate_constructed;
 
215
 
 
216
  pspec = g_param_spec_string ("object-path",
 
217
      "D-Bus object path",
 
218
      "The D-Bus object path used for this object on the bus.",
 
219
      NULL,
 
220
      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
221
  g_object_class_install_property (oclass, PROP_OBJECT_PATH, pspec);
 
222
 
 
223
  pspec = g_param_spec_uint ("state",
 
224
      "State of this certificate",
 
225
      "The state of this TLS certificate.",
 
226
      0, NUM_TP_TLS_CERTIFICATE_STATES - 1,
 
227
      TP_TLS_CERTIFICATE_STATE_PENDING,
 
228
      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
229
  g_object_class_install_property (oclass, PROP_STATE, pspec);
 
230
 
 
231
  pspec = g_param_spec_boxed ("rejections",
 
232
      "The reject reasons",
 
233
      "The reasons why this TLS certificate has been rejected",
 
234
      TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST,
 
235
      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
236
  g_object_class_install_property (oclass, PROP_REJECTIONS, pspec);
 
237
 
 
238
  pspec = g_param_spec_string ("certificate-type",
 
239
      "The certificate type",
 
240
      "The type of this certificate.",
 
241
      NULL,
 
242
      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
243
  g_object_class_install_property (oclass, PROP_CERTIFICATE_TYPE, pspec);
 
244
 
 
245
  pspec = g_param_spec_boxed ("certificate-chain-data",
 
246
      "The certificate chain data",
 
247
      "The raw PEM-encoded trust chain of this certificate.",
 
248
      TP_ARRAY_TYPE_UCHAR_ARRAY_LIST,
 
249
      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
250
  g_object_class_install_property (oclass, PROP_CERTIFICATE_CHAIN_DATA, pspec);
 
251
 
 
252
  pspec = g_param_spec_object ("dbus-daemon",
 
253
      "The DBus daemon connection",
 
254
      "The connection to the DBus daemon owning the CM",
 
255
      TP_TYPE_DBUS_DAEMON,
 
256
      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
 
257
  g_object_class_install_property (oclass, PROP_DBUS_DAEMON, pspec);
 
258
 
 
259
  klass->dbus_props_class.interfaces = prop_interfaces;
 
260
  tp_dbus_properties_mixin_class_init (oclass,
 
261
      G_STRUCT_OFFSET (IdleTLSCertificateClass, dbus_props_class));
 
262
}
 
263
 
 
264
static void
 
265
idle_tls_certificate_accept (TpSvcAuthenticationTLSCertificate *cert,
 
266
    DBusGMethodInvocation *context)
 
267
{
 
268
  IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (cert);
 
269
 
 
270
  IDLE_DEBUG ("Accept() called on the TLS certificate; current state %u",
 
271
      self->priv->cert_state);
 
272
 
 
273
  if (self->priv->cert_state != TP_TLS_CERTIFICATE_STATE_PENDING)
 
274
    {
 
275
      GError error =
 
276
        { TP_ERROR,
 
277
          TP_ERROR_INVALID_ARGUMENT,
 
278
          "Calling Accept() on a certificate with state != PENDING "
 
279
          "doesn't make sense."
 
280
        };
 
281
 
 
282
      dbus_g_method_return_error (context, &error);
 
283
      return;
 
284
    }
 
285
 
 
286
  self->priv->cert_state = TP_TLS_CERTIFICATE_STATE_ACCEPTED;
 
287
  tp_svc_authentication_tls_certificate_emit_accepted (self);
 
288
 
 
289
  tp_svc_authentication_tls_certificate_return_from_accept (context);
 
290
}
 
291
 
 
292
static void
 
293
idle_tls_certificate_reject (TpSvcAuthenticationTLSCertificate *cert,
 
294
    const GPtrArray *rejections,
 
295
    DBusGMethodInvocation *context)
 
296
{
 
297
  IdleTLSCertificate *self = IDLE_TLS_CERTIFICATE (cert);
 
298
 
 
299
  IDLE_DEBUG ("Reject() called on the TLS certificate with rejections %p, "
 
300
      "length %u; current state %u", rejections, rejections->len,
 
301
      self->priv->cert_state);
 
302
 
 
303
  if (rejections->len < 1)
 
304
    {
 
305
      GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
 
306
          "Calling Reject() with a zero-length rejection list." };
 
307
 
 
308
      dbus_g_method_return_error (context, &error);
 
309
      return;
 
310
    }
 
311
 
 
312
  if (self->priv->cert_state != TP_TLS_CERTIFICATE_STATE_PENDING)
 
313
    {
 
314
      GError error =
 
315
        { TP_ERROR,
 
316
          TP_ERROR_INVALID_ARGUMENT,
 
317
          "Calling Reject() on a certificate with state != PENDING "
 
318
          "doesn't make sense."
 
319
        };
 
320
 
 
321
      dbus_g_method_return_error (context, &error);
 
322
      return;
 
323
    }
 
324
 
 
325
  tp_clear_boxed (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST,
 
326
      &self->priv->rejections);
 
327
 
 
328
  self->priv->rejections =
 
329
    g_boxed_copy (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST,
 
330
        rejections);
 
331
  self->priv->cert_state = TP_TLS_CERTIFICATE_STATE_REJECTED;
 
332
 
 
333
  tp_svc_authentication_tls_certificate_emit_rejected (
 
334
      self, self->priv->rejections);
 
335
 
 
336
  tp_svc_authentication_tls_certificate_return_from_reject (context);
 
337
}
 
338
 
 
339
static void
 
340
tls_certificate_iface_init (gpointer g_iface,
 
341
    gpointer iface_data)
 
342
{
 
343
  TpSvcAuthenticationTLSCertificateClass *klass = g_iface;
 
344
 
 
345
#define IMPLEMENT(x) \
 
346
  tp_svc_authentication_tls_certificate_implement_##x ( \
 
347
      klass, idle_tls_certificate_##x)
 
348
  IMPLEMENT (accept);
 
349
  IMPLEMENT (reject);
 
350
#undef IMPLEMENT
 
351
}