gnutls: use g_clear_object()
[platform/upstream/glib-networking.git] / tls / gnutls / gtlsconnection-gnutls.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright 2009 Red Hat, Inc
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, see
17  * <http://www.gnu.org/licenses/>.
18  */
19
20 #include "config.h"
21 #include "glib.h"
22
23 #include <errno.h>
24 #include <gnutls/gnutls.h>
25 #include <gnutls/x509.h>
26
27 #include "gtlsconnection-gnutls.h"
28 #include "gtlsbackend-gnutls.h"
29 #include "gtlscertificate-gnutls.h"
30 #include "gtlsinputstream-gnutls.h"
31 #include "gtlsoutputstream-gnutls.h"
32 #include "gtlsserverconnection-gnutls.h"
33
34 #ifdef HAVE_PKCS11
35 #include <p11-kit/pin.h>
36 #include "pkcs11/gpkcs11pin.h"
37 #endif
38
39 #include <glib/gi18n-lib.h>
40
41 static ssize_t g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t  transport_data,
42                                                   const void             *buf,
43                                                   size_t                  buflen);
44 static ssize_t g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t  transport_data,
45                                                   void                   *buf,
46                                                   size_t                  buflen);
47
48 static void     g_tls_connection_gnutls_initable_iface_init (GInitableIface  *iface);
49 static gboolean g_tls_connection_gnutls_initable_init       (GInitable       *initable,
50                                                              GCancellable    *cancellable,
51                                                              GError         **error);
52
53 #ifdef HAVE_PKCS11
54 static P11KitPin*    on_pin_prompt_callback  (const char     *pinfile,
55                                               P11KitUri      *pin_uri,
56                                               const char     *pin_description,
57                                               P11KitPinFlags  pin_flags,
58                                               void           *callback_data);
59 #endif
60
61 static void g_tls_connection_gnutls_init_priorities (void);
62
63 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GTlsConnectionGnutls, g_tls_connection_gnutls, G_TYPE_TLS_CONNECTION,
64                                   G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
65                                                          g_tls_connection_gnutls_initable_iface_init);
66                                   g_tls_connection_gnutls_init_priorities ();
67                                   );
68
69
70 enum
71 {
72   PROP_0,
73   PROP_BASE_IO_STREAM,
74   PROP_REQUIRE_CLOSE_NOTIFY,
75   PROP_REHANDSHAKE_MODE,
76   PROP_USE_SYSTEM_CERTDB,
77   PROP_DATABASE,
78   PROP_CERTIFICATE,
79   PROP_INTERACTION,
80   PROP_PEER_CERTIFICATE,
81   PROP_PEER_CERTIFICATE_ERRORS
82 };
83
84 struct _GTlsConnectionGnutlsPrivate
85 {
86   GIOStream *base_io_stream;
87   GPollableInputStream *base_istream;
88   GPollableOutputStream *base_ostream;
89
90   gnutls_certificate_credentials creds;
91   gnutls_session session;
92
93   GTlsCertificate *certificate, *peer_certificate;
94   GTlsCertificateFlags peer_certificate_errors;
95   gboolean require_close_notify;
96   GTlsRehandshakeMode rehandshake_mode;
97   gboolean is_system_certdb;
98   GTlsDatabase *database;
99   gboolean database_is_unset;
100   gboolean need_handshake, handshaking, ever_handshaked;
101   gboolean closing;
102
103   GInputStream *tls_istream;
104   GOutputStream *tls_ostream;
105
106   GTlsInteraction *interaction;
107   gchar *interaction_id;
108
109   GError *error;
110   GCancellable *cancellable;
111   gboolean blocking;
112 #ifndef GNUTLS_E_PREMATURE_TERMINATION
113   gboolean eof;
114 #endif
115   GIOCondition internal_direction;
116 };
117
118 static gint unique_interaction_id = 0;
119
120 static void
121 g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
122 {
123   gint unique_id;
124
125   gnutls->priv = G_TYPE_INSTANCE_GET_PRIVATE (gnutls, G_TYPE_TLS_CONNECTION_GNUTLS, GTlsConnectionGnutlsPrivate);
126
127   gnutls_certificate_allocate_credentials (&gnutls->priv->creds);
128   gnutls_certificate_set_verify_flags (gnutls->priv->creds,
129                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
130
131   gnutls->priv->need_handshake = TRUE;
132
133   gnutls->priv->database_is_unset = TRUE;
134   gnutls->priv->is_system_certdb = TRUE;
135
136   unique_id = g_atomic_int_add (&unique_interaction_id, 1);
137   gnutls->priv->interaction_id = g_strdup_printf ("gtls:%d", unique_id);
138
139 #ifdef HAVE_PKCS11
140   p11_kit_pin_register_callback (gnutls->priv->interaction_id,
141                                  on_pin_prompt_callback, gnutls, NULL);
142 #endif
143 }
144
145 static gnutls_priority_t priorities[2][2];
146
147 static void
148 g_tls_connection_gnutls_init_priorities (void)
149 {
150   /* First field is "ssl3 only", second is "allow unsafe rehandshaking" */
151
152   gnutls_priority_init (&priorities[FALSE][FALSE],
153                         "NORMAL:%COMPAT",
154                         NULL);
155   gnutls_priority_init (&priorities[TRUE][FALSE],
156                         "NORMAL:%COMPAT:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0",
157                         NULL);
158   gnutls_priority_init (&priorities[FALSE][TRUE],
159                         "NORMAL:%COMPAT:%UNSAFE_RENEGOTIATION",
160                         NULL);
161   gnutls_priority_init (&priorities[TRUE][TRUE],
162                         "NORMAL:%COMPAT:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0:%UNSAFE_RENEGOTIATION",
163                         NULL);
164 }
165
166 static void
167 g_tls_connection_gnutls_set_handshake_priority (GTlsConnectionGnutls *gnutls)
168 {
169   gboolean use_ssl3, unsafe_rehandshake;
170
171   if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
172     use_ssl3 = g_tls_client_connection_get_use_ssl3 (G_TLS_CLIENT_CONNECTION (gnutls));
173   else
174     use_ssl3 = FALSE;
175   unsafe_rehandshake = (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_UNSAFELY);
176   gnutls_priority_set (gnutls->priv->session,
177                        priorities[use_ssl3][unsafe_rehandshake]);
178 }
179
180 static gboolean
181 g_tls_connection_gnutls_initable_init (GInitable     *initable,
182                                        GCancellable  *cancellable,
183                                        GError       **error)
184 {
185   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (initable);
186   int status;
187
188   g_return_val_if_fail (gnutls->priv->base_istream != NULL &&
189                         gnutls->priv->base_ostream != NULL, FALSE);
190
191   /* Make sure gnutls->priv->session has been initialized (it may have
192    * already been initialized by a construct-time property setter).
193    */
194   g_tls_connection_gnutls_get_session (gnutls);
195
196   status = gnutls_credentials_set (gnutls->priv->session,
197                                    GNUTLS_CRD_CERTIFICATE,
198                                    gnutls->priv->creds);
199   if (status != 0)
200     {
201       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
202                    _("Could not create TLS connection: %s"),
203                    gnutls_strerror (status));
204       return FALSE;
205     }
206
207   /* Some servers (especially on embedded devices) use tiny keys that
208    * gnutls will reject by default. We want it to accept them.
209    */
210   gnutls_dh_set_prime_bits (gnutls->priv->session, 256);
211
212   gnutls_transport_set_push_function (gnutls->priv->session,
213                                       g_tls_connection_gnutls_push_func);
214   gnutls_transport_set_pull_function (gnutls->priv->session,
215                                       g_tls_connection_gnutls_pull_func);
216   gnutls_transport_set_ptr (gnutls->priv->session, gnutls);
217
218   gnutls->priv->tls_istream = g_tls_input_stream_gnutls_new (gnutls);
219   gnutls->priv->tls_ostream = g_tls_output_stream_gnutls_new (gnutls);
220
221   return TRUE;
222 }
223
224 static void
225 g_tls_connection_gnutls_finalize (GObject *object)
226 {
227   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
228
229   g_clear_object (&gnutls->priv->base_io_stream);
230
231   g_clear_object (&gnutls->priv->tls_istream);
232   g_clear_object (&gnutls->priv->tls_ostream);
233
234   if (gnutls->priv->session)
235     gnutls_deinit (gnutls->priv->session);
236   if (gnutls->priv->creds)
237     gnutls_certificate_free_credentials (gnutls->priv->creds);
238
239   g_clear_object (&gnutls->priv->database);
240   g_clear_object (&gnutls->priv->certificate);
241   g_clear_object (&gnutls->priv->peer_certificate);
242
243 #ifdef HAVE_PKCS11
244   p11_kit_pin_unregister_callback (gnutls->priv->interaction_id,
245                                    on_pin_prompt_callback, gnutls);
246 #endif
247   g_free (gnutls->priv->interaction_id);
248   g_clear_object (&gnutls->priv->interaction);
249
250   g_clear_error (&gnutls->priv->error);
251
252   G_OBJECT_CLASS (g_tls_connection_gnutls_parent_class)->finalize (object);
253 }
254
255 static void
256 g_tls_connection_gnutls_get_property (GObject    *object,
257                                       guint       prop_id,
258                                       GValue     *value,
259                                       GParamSpec *pspec)
260 {
261   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
262   GTlsBackend *backend;
263
264   switch (prop_id)
265     {
266     case PROP_BASE_IO_STREAM:
267       g_value_set_object (value, gnutls->priv->base_io_stream);
268       break;
269
270     case PROP_REQUIRE_CLOSE_NOTIFY:
271       g_value_set_boolean (value, gnutls->priv->require_close_notify);
272       break;
273
274     case PROP_REHANDSHAKE_MODE:
275       g_value_set_enum (value, gnutls->priv->rehandshake_mode);
276       break;
277
278     case PROP_USE_SYSTEM_CERTDB:
279       g_value_set_boolean (value, gnutls->priv->is_system_certdb);
280       break;
281
282     case PROP_DATABASE:
283       if (gnutls->priv->database_is_unset)
284         {
285           backend = g_tls_backend_get_default ();
286           gnutls->priv->database =  g_tls_backend_get_default_database (backend);
287           gnutls->priv->database_is_unset = FALSE;
288         }
289       g_value_set_object (value, gnutls->priv->database);
290       break;
291
292     case PROP_CERTIFICATE:
293       g_value_set_object (value, gnutls->priv->certificate);
294       break;
295
296     case PROP_INTERACTION:
297       g_value_set_object (value, gnutls->priv->interaction);
298       break;
299
300     case PROP_PEER_CERTIFICATE:
301       g_value_set_object (value, gnutls->priv->peer_certificate);
302       break;
303
304     case PROP_PEER_CERTIFICATE_ERRORS:
305       g_value_set_flags (value, gnutls->priv->peer_certificate_errors);
306       break;
307
308     default:
309       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
310     }
311 }
312
313 static void
314 g_tls_connection_gnutls_set_property (GObject      *object,
315                                       guint         prop_id,
316                                       const GValue *value,
317                                       GParamSpec   *pspec)
318 {
319   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
320   GInputStream *istream;
321   GOutputStream *ostream;
322   gboolean system_certdb;
323   GTlsBackend *backend;
324
325   switch (prop_id)
326     {
327     case PROP_BASE_IO_STREAM:
328       if (gnutls->priv->base_io_stream)
329         {
330           g_object_unref (gnutls->priv->base_io_stream);
331           gnutls->priv->base_istream = NULL;
332           gnutls->priv->base_ostream = NULL;
333         }
334       gnutls->priv->base_io_stream = g_value_dup_object (value);
335       if (!gnutls->priv->base_io_stream)
336         return;
337
338       istream = g_io_stream_get_input_stream (gnutls->priv->base_io_stream);
339       ostream = g_io_stream_get_output_stream (gnutls->priv->base_io_stream);
340
341       if (G_IS_POLLABLE_INPUT_STREAM (istream) &&
342           g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (istream)))
343         gnutls->priv->base_istream = G_POLLABLE_INPUT_STREAM (istream);
344       if (G_IS_POLLABLE_OUTPUT_STREAM (ostream) &&
345           g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (ostream)))
346         gnutls->priv->base_ostream = G_POLLABLE_OUTPUT_STREAM (ostream);
347       break;
348
349     case PROP_REQUIRE_CLOSE_NOTIFY:
350       gnutls->priv->require_close_notify = g_value_get_boolean (value);
351       break;
352
353     case PROP_REHANDSHAKE_MODE:
354       gnutls->priv->rehandshake_mode = g_value_get_enum (value);
355       break;
356
357     case PROP_USE_SYSTEM_CERTDB:
358       system_certdb = g_value_get_boolean (value);
359       if (system_certdb != gnutls->priv->is_system_certdb)
360         {
361           g_clear_object (&gnutls->priv->database);
362           if (system_certdb)
363             {
364               backend = g_tls_backend_get_default ();
365               gnutls->priv->database = g_tls_backend_get_default_database (backend);
366             }
367           gnutls->priv->is_system_certdb = system_certdb;
368           gnutls->priv->database_is_unset = FALSE;
369         }
370       break;
371
372     case PROP_DATABASE:
373       g_clear_object (&gnutls->priv->database);
374       gnutls->priv->database = g_value_dup_object (value);
375       gnutls->priv->is_system_certdb = FALSE;
376       gnutls->priv->database_is_unset = FALSE;
377       break;
378
379     case PROP_CERTIFICATE:
380       if (gnutls->priv->certificate)
381         g_object_unref (gnutls->priv->certificate);
382       gnutls->priv->certificate = g_value_dup_object (value);
383       break;
384
385     case PROP_INTERACTION:
386       g_clear_object (&gnutls->priv->interaction);
387       gnutls->priv->interaction = g_value_dup_object (value);
388       break;
389
390     default:
391       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
392     }
393 }
394
395 gnutls_certificate_credentials
396 g_tls_connection_gnutls_get_credentials (GTlsConnectionGnutls *gnutls)
397 {
398   return gnutls->priv->creds;
399 }
400
401 gnutls_session
402 g_tls_connection_gnutls_get_session (GTlsConnectionGnutls *gnutls)
403 {
404   /* Ideally we would initialize gnutls->priv->session from
405    * g_tls_connection_gnutls_init(), but we can't tell if it's a
406    * client or server connection at that point... And
407    * g_tls_connection_gnutls_initiable_init() is too late, because
408    * construct-time property setters may need to modify it.
409    */
410   if (!gnutls->priv->session)
411     {
412       gboolean client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
413       gnutls_init (&gnutls->priv->session, client ? GNUTLS_CLIENT : GNUTLS_SERVER);
414     }
415
416   return gnutls->priv->session;
417 }
418
419 void
420 g_tls_connection_gnutls_get_certificate (GTlsConnectionGnutls *gnutls,
421                                          gnutls_retr2_st      *st)
422 {
423   GTlsCertificate *cert;
424
425   cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (gnutls));
426
427   st->cert_type = GNUTLS_CRT_X509;
428   st->ncerts = 0;
429
430   if (cert)
431       g_tls_certificate_gnutls_copy (G_TLS_CERTIFICATE_GNUTLS (cert),
432                                      gnutls->priv->interaction_id, st);
433 }
434
435 static void
436 begin_gnutls_io (GTlsConnectionGnutls  *gnutls,
437                  gboolean               blocking,
438                  GCancellable          *cancellable)
439 {
440   gnutls->priv->blocking = blocking;
441   gnutls->priv->cancellable = cancellable;
442   gnutls->priv->internal_direction = 0;
443   if (cancellable)
444     g_cancellable_push_current (cancellable);
445   g_clear_error (&gnutls->priv->error);
446 }
447
448 static int
449 end_gnutls_io (GTlsConnectionGnutls  *gnutls,
450                int                    status,
451                GError               **error)
452 {
453   if (gnutls->priv->cancellable)
454     g_cancellable_pop_current (gnutls->priv->cancellable);
455   gnutls->priv->cancellable = NULL;
456
457   if (status >= 0)
458     {
459       g_clear_error (&gnutls->priv->error);
460       return status;
461     }
462
463   if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
464     {
465       if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
466           status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH ||
467           status == GNUTLS_E_FATAL_ALERT_RECEIVED ||
468           status == GNUTLS_E_DECRYPTION_FAILED ||
469           status == GNUTLS_E_UNSUPPORTED_VERSION_PACKET)
470         {
471           g_clear_error (&gnutls->priv->error);
472           g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS,
473                                _("Peer failed to perform TLS handshake"));
474           return GNUTLS_E_PULL_ERROR;
475         }
476     }
477
478   if (gnutls->priv->error)
479     {
480       if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
481         status = GNUTLS_E_AGAIN;
482       else
483         G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->failed (gnutls);
484       g_propagate_error (error, gnutls->priv->error);
485       gnutls->priv->error = NULL;
486       return status;
487     }
488   else if (status == GNUTLS_E_REHANDSHAKE)
489     {
490       if (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_NEVER)
491         {
492           g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
493                                _("Peer requested illegal TLS rehandshake"));
494           return GNUTLS_E_PULL_ERROR;
495         }
496
497       gnutls->priv->need_handshake = TRUE;
498       return status;
499     }
500   else if (
501 #ifdef GNUTLS_E_PREMATURE_TERMINATION
502            status == GNUTLS_E_PREMATURE_TERMINATION
503 #else
504            status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH && gnutls->priv->eof
505 #endif
506            )
507     {
508       if (gnutls->priv->require_close_notify)
509         {
510           g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_EOF,
511                                _("TLS connection closed unexpectedly"));
512           G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->failed (gnutls);
513           return status;
514         }
515       else
516         return 0;
517     }
518
519   return status;
520 }
521
522 #define BEGIN_GNUTLS_IO(gnutls, blocking, cancellable)  \
523   begin_gnutls_io (gnutls, blocking, cancellable);      \
524   do {
525
526 #define END_GNUTLS_IO(gnutls, ret, errmsg, error)       \
527   } while ((ret == GNUTLS_E_AGAIN ||                    \
528             ret == GNUTLS_E_WARNING_ALERT_RECEIVED) &&  \
529            !gnutls->priv->error);                       \
530   ret = end_gnutls_io (gnutls, ret, error);             \
531   if (ret < 0 && ret != GNUTLS_E_REHANDSHAKE && error && !*error) \
532     {                                                   \
533       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,\
534                    errmsg, gnutls_strerror (ret));      \
535     }                                                   \
536   ;
537
538 gboolean
539 g_tls_connection_gnutls_check (GTlsConnectionGnutls  *gnutls,
540                                GIOCondition           condition)
541 {
542   if (!gnutls->priv->internal_direction)
543     return TRUE;
544
545   if (gnutls->priv->handshaking || gnutls->priv->closing)
546     condition = gnutls->priv->internal_direction;
547
548   if (condition & G_IO_IN)
549     return g_pollable_input_stream_is_readable (gnutls->priv->base_istream);
550   else
551     return g_pollable_output_stream_is_writable (gnutls->priv->base_ostream);
552 }
553
554 typedef struct {
555   GSource source;
556
557   GTlsConnectionGnutls *gnutls;
558   GObject              *stream;
559
560   GSource              *child_source;
561   GIOCondition          current_direction;
562 } GTlsConnectionGnutlsSource;
563
564 static gboolean
565 gnutls_source_prepare (GSource *source,
566                        gint    *timeout)
567 {
568   *timeout = -1;
569   return FALSE;
570 }
571
572 static gboolean
573 gnutls_source_check (GSource *source)
574 {
575   return FALSE;
576 }
577
578 static gboolean
579 gnutls_source_sync_child_source (GTlsConnectionGnutlsSource *gnutls_source)
580 {
581   GTlsConnectionGnutls *gnutls = gnutls_source->gnutls;
582   GSource *source = (GSource *)gnutls_source;
583   GIOCondition direction;
584
585   if (gnutls->priv->handshaking || gnutls->priv->closing)
586     direction = gnutls->priv->internal_direction;
587   else if (!gnutls_source->stream)
588     return FALSE;
589   else if (G_IS_TLS_INPUT_STREAM_GNUTLS (gnutls_source->stream))
590     direction = G_IO_IN;
591   else
592     direction = G_IO_OUT;
593
594   if (direction == gnutls_source->current_direction)
595     return TRUE;
596
597   if (gnutls_source->child_source)
598     {
599       g_source_remove_child_source (source, gnutls_source->child_source);
600       g_source_unref (gnutls_source->child_source);
601     }
602
603   if (direction & G_IO_IN)
604     gnutls_source->child_source = g_pollable_input_stream_create_source (gnutls->priv->base_istream, NULL);
605   else
606     gnutls_source->child_source = g_pollable_output_stream_create_source (gnutls->priv->base_ostream, NULL);
607
608   g_source_set_dummy_callback (gnutls_source->child_source);
609   g_source_add_child_source (source, gnutls_source->child_source);
610   gnutls_source->current_direction = direction;
611   return TRUE;
612 }
613
614 static gboolean
615 gnutls_source_dispatch (GSource     *source,
616                         GSourceFunc  callback,
617                         gpointer     user_data)
618 {
619   GPollableSourceFunc func = (GPollableSourceFunc)callback;
620   GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
621   gboolean ret;
622
623   ret = (*func) (gnutls_source->stream, user_data);
624   if (ret)
625     ret = gnutls_source_sync_child_source (gnutls_source);
626
627   return ret;
628 }
629
630 static void
631 gnutls_source_finalize (GSource *source)
632 {
633   GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
634
635   g_object_unref (gnutls_source->gnutls);
636
637   if (gnutls_source->child_source)
638     g_source_unref (gnutls_source->child_source);
639 }
640
641 static gboolean
642 g_tls_connection_gnutls_source_closure_callback (GObject  *stream,
643                                                  gpointer  data)
644 {
645   GClosure *closure = data;
646
647   GValue param = { 0, };
648   GValue result_value = { 0, };
649   gboolean result;
650
651   g_value_init (&result_value, G_TYPE_BOOLEAN);
652
653   g_value_init (&param, G_TYPE_OBJECT);
654   g_value_set_object (&param, stream);
655
656   g_closure_invoke (closure, &result_value, 1, &param, NULL);
657
658   result = g_value_get_boolean (&result_value);
659   g_value_unset (&result_value);
660   g_value_unset (&param);
661
662   return result;
663 }
664
665 static GSourceFuncs gnutls_source_funcs =
666 {
667   gnutls_source_prepare,
668   gnutls_source_check,
669   gnutls_source_dispatch,
670   gnutls_source_finalize,
671   (GSourceFunc)g_tls_connection_gnutls_source_closure_callback,
672   (GSourceDummyMarshal)g_cclosure_marshal_generic
673 };
674
675 GSource *
676 g_tls_connection_gnutls_create_source (GTlsConnectionGnutls  *gnutls,
677                                        GIOCondition           condition,
678                                        GCancellable          *cancellable)
679 {
680   GSource *source, *cancellable_source;
681   GTlsConnectionGnutlsSource *gnutls_source;
682
683   source = g_source_new (&gnutls_source_funcs, sizeof (GTlsConnectionGnutlsSource));
684   g_source_set_name (source, "GTlsConnectionGnutlsSource");
685   gnutls_source = (GTlsConnectionGnutlsSource *)source;
686   gnutls_source->gnutls = g_object_ref (gnutls);
687   if (condition & G_IO_IN)
688     gnutls_source->stream = G_OBJECT (gnutls->priv->tls_istream);
689   else if (condition & G_IO_OUT)
690     gnutls_source->stream = G_OBJECT (gnutls->priv->tls_ostream);
691   gnutls_source_sync_child_source (gnutls_source);
692
693   if (cancellable)
694     {
695       cancellable_source = g_cancellable_source_new (cancellable);
696       g_source_set_dummy_callback (cancellable_source);
697       g_source_add_child_source (source, cancellable_source);
698       g_source_unref (cancellable_source);
699     }
700
701   return source;
702 }
703
704 static void
705 set_gnutls_error (GTlsConnectionGnutls *gnutls, GIOCondition direction)
706 {
707   if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
708     gnutls_transport_set_errno (gnutls->priv->session, EINTR);
709   else if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
710     {
711       gnutls_transport_set_errno (gnutls->priv->session, EAGAIN);
712       gnutls->priv->internal_direction = direction;
713     }
714   else
715     gnutls_transport_set_errno (gnutls->priv->session, EIO);
716 }
717
718 static ssize_t
719 g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t  transport_data,
720                                    void                   *buf,
721                                    size_t                  buflen)
722 {
723   GTlsConnectionGnutls *gnutls = transport_data;
724   ssize_t ret;
725
726   /* If gnutls->priv->error is non-%NULL when we're called, it means
727    * that an error previously occurred, but gnutls decided not to
728    * propagate it. So it's correct for us to just clear it. (Usually
729    * this means it ignored an EAGAIN after a short read, and now
730    * we'll return EAGAIN again, which it will obey this time.)
731    */
732   g_clear_error (&gnutls->priv->error);
733
734   ret = g_pollable_stream_read (G_INPUT_STREAM (gnutls->priv->base_istream),
735                                 buf, buflen, gnutls->priv->blocking,
736                                 gnutls->priv->cancellable,
737                                 &gnutls->priv->error);
738
739   if (ret < 0)
740     set_gnutls_error (gnutls, G_IO_IN);
741 #ifndef GNUTLS_E_PREMATURE_TERMINATION
742   else if (ret == 0)
743     gnutls->priv->eof = TRUE;
744 #endif
745
746   return ret;
747 }
748
749 static ssize_t
750 g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t  transport_data,
751                                    const void             *buf,
752                                    size_t                  buflen)
753 {
754   GTlsConnectionGnutls *gnutls = transport_data;
755   ssize_t ret;
756
757   /* See comment in pull_func. */
758   g_clear_error (&gnutls->priv->error);
759
760   ret = g_pollable_stream_write (G_OUTPUT_STREAM (gnutls->priv->base_ostream),
761                                  buf, buflen, gnutls->priv->blocking,
762                                  gnutls->priv->cancellable,
763                                  &gnutls->priv->error);
764   if (ret < 0)
765     set_gnutls_error (gnutls, G_IO_OUT);
766
767   return ret;
768 }
769
770 static gboolean
771 handshake_internal (GTlsConnectionGnutls  *gnutls,
772                     gboolean               blocking,
773                     GCancellable          *cancellable,
774                     GError               **error)
775 {
776   GTlsCertificate *peer_certificate = NULL;
777   GTlsCertificateFlags peer_certificate_errors = 0;
778   int ret;
779
780   if (G_IS_TLS_SERVER_CONNECTION_GNUTLS (gnutls) &&
781       gnutls->priv->ever_handshaked && !gnutls->priv->handshaking &&
782       !gnutls->priv->need_handshake)
783     {
784       BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
785       ret = gnutls_rehandshake (gnutls->priv->session);
786       END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
787
788       if (ret != 0)
789         return FALSE;
790     }
791
792   if (!gnutls->priv->handshaking)
793     {
794       gnutls->priv->handshaking = TRUE;
795
796       if (gnutls->priv->peer_certificate)
797         {
798           g_clear_object (&gnutls->priv->peer_certificate);
799           gnutls->priv->peer_certificate_errors = 0;
800
801           g_object_notify (G_OBJECT (gnutls), "peer-certificate");
802           g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
803         }
804
805       g_tls_connection_gnutls_set_handshake_priority (gnutls);
806       G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->begin_handshake (gnutls);
807     }
808
809   BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
810   ret = gnutls_handshake (gnutls->priv->session);
811   END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
812
813   if (ret == GNUTLS_E_AGAIN)
814     return FALSE;
815
816   gnutls->priv->handshaking = FALSE;
817   gnutls->priv->need_handshake = FALSE;
818   gnutls->priv->ever_handshaked = TRUE;
819
820   if (ret == 0 &&
821       gnutls_certificate_type_get (gnutls->priv->session) == GNUTLS_CRT_X509)
822     {
823       GTlsCertificate *chain, *cert;
824       const gnutls_datum_t *certs;
825       unsigned int num_certs;
826       int i;
827
828       certs = gnutls_certificate_get_peers (gnutls->priv->session, &num_certs);
829       chain = NULL;
830       if (certs)
831         {
832           for (i = num_certs - 1; i >= 0; i--)
833             {
834               cert = g_tls_certificate_gnutls_new (&certs[i], chain);
835               if (chain)
836                 g_object_unref (chain);
837               chain = cert;
838             }
839         }
840
841       peer_certificate = chain;
842     }
843
844   if (peer_certificate)
845     {
846       gboolean accepted;
847
848       accepted = G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->verify_peer (gnutls, peer_certificate, &peer_certificate_errors);
849
850       gnutls->priv->peer_certificate = peer_certificate;
851       gnutls->priv->peer_certificate_errors = peer_certificate_errors;
852
853       g_object_notify (G_OBJECT (gnutls), "peer-certificate");
854       g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
855
856       if (!accepted)
857         {
858           g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
859                                _("Unacceptable TLS certificate"));
860           return FALSE;
861         }
862     }
863
864   G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->finish_handshake (gnutls, ret == 0, error);
865   return (ret == 0);
866 }
867
868 static gboolean
869 handshake_in_progress_or_failed (GTlsConnectionGnutls  *gnutls,
870                                  gboolean               blocking,
871                                  GCancellable          *cancellable,
872                                  GError               **error)
873 {
874   if (!(gnutls->priv->need_handshake || gnutls->priv->handshaking))
875     return FALSE;
876
877   return !handshake_internal (gnutls, blocking, cancellable, error);
878 }
879
880 static gboolean
881 g_tls_connection_gnutls_handshake (GTlsConnection   *conn,
882                                    GCancellable     *cancellable,
883                                    GError          **error)
884 {
885   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
886
887   return handshake_internal (gnutls, TRUE, cancellable, error);
888 }
889
890 static gboolean
891 g_tls_connection_gnutls_handshake_ready (GObject  *pollable_stream,
892                                          gpointer  user_data)
893 {
894   GTlsConnectionGnutls *gnutls;
895   GSimpleAsyncResult *simple = user_data;
896   gboolean success;
897   GError *error = NULL;
898
899   gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
900   g_object_unref (gnutls);
901
902   success = handshake_internal (gnutls, FALSE, NULL, &error);
903   if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
904     {
905       g_error_free (error);
906       return TRUE;
907     }
908
909   if (error)
910     {
911       g_simple_async_result_set_from_error (simple, error);
912       g_error_free (error);
913     }
914   else
915     g_simple_async_result_set_op_res_gboolean (simple, success);
916   g_simple_async_result_complete (simple);
917   g_object_unref (simple);
918
919   return FALSE;
920 }
921
922 static void
923 g_tls_connection_gnutls_handshake_async (GTlsConnection       *conn,
924                                          int                   io_priority,
925                                          GCancellable         *cancellable,
926                                          GAsyncReadyCallback   callback,
927                                          gpointer              user_data)
928 {
929   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
930   GSimpleAsyncResult *simple;
931   gboolean success;
932   GError *error = NULL;
933   GSource *source;
934
935   simple = g_simple_async_result_new (G_OBJECT (conn), callback, user_data,
936                                       g_tls_connection_gnutls_handshake_async);
937   success = handshake_internal (gnutls, FALSE, cancellable, &error);
938   if (success)
939     {
940       g_simple_async_result_set_op_res_gboolean (simple, TRUE);
941       g_simple_async_result_complete_in_idle (simple);
942       g_object_unref (simple);
943       return;
944     }
945   else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
946     {
947       g_simple_async_result_set_from_error (simple, error);
948       g_error_free (error);
949       g_simple_async_result_complete_in_idle (simple);
950       g_object_unref (simple);
951       return;
952     }
953   else if (error)
954     g_error_free (error);
955
956   source = g_tls_connection_gnutls_create_source (gnutls, 0, cancellable);
957   g_source_set_callback (source,
958                          (GSourceFunc) g_tls_connection_gnutls_handshake_ready,
959                          simple, NULL);
960   g_source_set_priority (source, io_priority);
961   g_source_attach (source, g_main_context_get_thread_default ());
962   g_source_unref (source);
963 }
964
965 static gboolean
966 g_tls_connection_gnutls_handshake_finish (GTlsConnection       *conn,
967                                           GAsyncResult         *result,
968                                           GError              **error)
969 {
970   GSimpleAsyncResult *simple;
971
972   g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (conn), g_tls_connection_gnutls_handshake_async), FALSE);
973
974   simple = G_SIMPLE_ASYNC_RESULT (result);
975
976   if (g_simple_async_result_propagate_error (simple, error))
977     return FALSE;
978
979   return g_simple_async_result_get_op_res_gboolean (simple);
980 }
981
982 gssize
983 g_tls_connection_gnutls_read (GTlsConnectionGnutls  *gnutls,
984                               void                  *buffer,
985                               gsize                  count,
986                               gboolean               blocking,
987                               GCancellable          *cancellable,
988                               GError               **error)
989 {
990   gssize ret;
991
992  again:
993   if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
994     return -1;
995
996   BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
997   ret = gnutls_record_recv (gnutls->priv->session, buffer, count);
998   END_GNUTLS_IO (gnutls, ret, _("Error reading data from TLS socket: %s"), error);
999
1000   if (ret >= 0)
1001     return ret;
1002   else if (ret == GNUTLS_E_REHANDSHAKE)
1003     goto again;
1004   else
1005     return -1;
1006 }
1007
1008 gssize
1009 g_tls_connection_gnutls_write (GTlsConnectionGnutls  *gnutls,
1010                                const void            *buffer,
1011                                gsize                  count,
1012                                gboolean               blocking,
1013                                GCancellable          *cancellable,
1014                                GError               **error)
1015 {
1016   gssize ret;
1017
1018  again:
1019   if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1020     return -1;
1021
1022   BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1023   ret = gnutls_record_send (gnutls->priv->session, buffer, count);
1024   END_GNUTLS_IO (gnutls, ret, _("Error writing data to TLS socket: %s"), error);
1025
1026   if (ret >= 0)
1027     return ret;
1028   else if (ret == GNUTLS_E_REHANDSHAKE)
1029     goto again;
1030   else
1031     return -1;
1032 }
1033
1034 static GInputStream  *
1035 g_tls_connection_gnutls_get_input_stream (GIOStream *stream)
1036 {
1037   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1038
1039   return gnutls->priv->tls_istream;
1040 }
1041
1042 static GOutputStream *
1043 g_tls_connection_gnutls_get_output_stream (GIOStream *stream)
1044 {
1045   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1046
1047   return gnutls->priv->tls_ostream;
1048 }
1049
1050 static gboolean
1051 close_internal (GTlsConnectionGnutls  *gnutls,
1052                 gboolean               blocking,
1053                 GCancellable          *cancellable,
1054                 GError               **error)
1055 {
1056   int ret;
1057
1058   /* If we haven't finished the initial handshake yet, there's no
1059    * reason to finish it just so we can close.
1060    */
1061   if (!gnutls->priv->ever_handshaked)
1062     return TRUE;
1063
1064   if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1065     return FALSE;
1066
1067   gnutls->priv->closing = TRUE;
1068   BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1069   ret = gnutls_bye (gnutls->priv->session, GNUTLS_SHUT_WR);
1070   END_GNUTLS_IO (gnutls, ret, _("Error performing TLS close: %s"), error);
1071   if (ret == 0 || !error || !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1072     gnutls->priv->closing = FALSE;
1073
1074   return ret == 0;
1075 }
1076
1077 static gboolean
1078 g_tls_connection_gnutls_close (GIOStream     *stream,
1079                                GCancellable  *cancellable,
1080                                GError       **error)
1081 {
1082   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1083
1084   if (!close_internal (gnutls, TRUE, cancellable, error))
1085     return FALSE;
1086   return g_io_stream_close (gnutls->priv->base_io_stream,
1087                             cancellable, error);
1088 }
1089
1090 typedef struct {
1091   GSimpleAsyncResult *simple;
1092   GCancellable *cancellable;
1093   int io_priority;
1094 } AsyncCloseData;
1095
1096 static void
1097 close_base_stream_cb (GObject      *base_stream,
1098                       GAsyncResult *result,
1099                       gpointer      user_data)
1100 {
1101   gboolean success;
1102   GError *error = NULL;
1103   AsyncCloseData *acd = user_data;
1104
1105   success = g_io_stream_close_finish (G_IO_STREAM (base_stream),
1106                                       result, &error);
1107   if (success)
1108     g_simple_async_result_set_op_res_gboolean (acd->simple, TRUE);
1109   else
1110     {
1111       g_simple_async_result_set_from_error (acd->simple, error);
1112       g_error_free (error);
1113     }
1114
1115   g_simple_async_result_complete (acd->simple);
1116   g_object_unref (acd->simple);
1117   if (acd->cancellable)
1118     g_object_unref (acd->cancellable);
1119   g_slice_free (AsyncCloseData, acd);
1120 }
1121
1122 static gboolean
1123 g_tls_connection_gnutls_close_ready (GObject  *pollable_stream,
1124                                      gpointer  user_data)
1125 {
1126   GTlsConnectionGnutls *gnutls;
1127   AsyncCloseData *acd = user_data;
1128   gboolean success;
1129   GError *error = NULL;
1130
1131   gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (acd->simple)));
1132   g_object_unref (gnutls);
1133
1134   success = close_internal (gnutls, FALSE, NULL, &error);
1135   if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1136     {
1137       g_error_free (error);
1138       return TRUE;
1139     }
1140
1141   if (error)
1142     {
1143       g_simple_async_result_set_from_error (acd->simple, error);
1144       g_simple_async_result_complete (acd->simple);
1145       g_error_free (error);
1146       g_object_unref (acd->simple);
1147       if (acd->cancellable)
1148         g_object_unref (acd->cancellable);
1149       g_slice_free (AsyncCloseData, acd);
1150     }
1151   else
1152     {
1153       g_io_stream_close_async (gnutls->priv->base_io_stream,
1154                                acd->io_priority, acd->cancellable,
1155                                close_base_stream_cb, acd);
1156     }
1157
1158   return FALSE;
1159 }
1160
1161 static void
1162 g_tls_connection_gnutls_close_async (GIOStream           *stream,
1163                                      int                  io_priority,
1164                                      GCancellable        *cancellable,
1165                                      GAsyncReadyCallback  callback,
1166                                      gpointer             user_data)
1167 {
1168   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1169   GSimpleAsyncResult *simple;
1170   gboolean success;
1171   GError *error = NULL;
1172   AsyncCloseData *acd;
1173   GSource *source;
1174
1175   simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
1176                                       g_tls_connection_gnutls_close_async);
1177
1178   success = close_internal (gnutls, FALSE, cancellable, &error);
1179   if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1180     {
1181       g_simple_async_result_set_from_error (simple, error);
1182       g_error_free (error);
1183       g_simple_async_result_complete_in_idle (simple);
1184       g_object_unref (simple);
1185     }
1186
1187   if (error)
1188     g_error_free (error);
1189
1190   acd = g_slice_new (AsyncCloseData);
1191   acd->simple = simple;
1192   acd->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
1193   acd->io_priority = io_priority;
1194
1195   if (success)
1196     {
1197       g_io_stream_close_async (gnutls->priv->base_io_stream,
1198                                io_priority, cancellable,
1199                                close_base_stream_cb, acd);
1200       return;
1201     }
1202
1203   source = g_tls_connection_gnutls_create_source (gnutls, 0, acd->cancellable);
1204   g_source_set_callback (source,
1205                          (GSourceFunc) g_tls_connection_gnutls_close_ready,
1206                          acd, NULL);
1207   g_source_set_priority (source, acd->io_priority);
1208   g_source_attach (source, g_main_context_get_thread_default ());
1209   g_source_unref (source);
1210 }
1211
1212 static gboolean
1213 g_tls_connection_gnutls_close_finish (GIOStream           *stream,
1214                                       GAsyncResult        *result,
1215                                       GError             **error)
1216 {
1217   GSimpleAsyncResult *simple;
1218
1219   g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (stream), g_tls_connection_gnutls_close_async), FALSE);
1220
1221   simple = G_SIMPLE_ASYNC_RESULT (result);
1222
1223   if (g_simple_async_result_propagate_error (simple, error))
1224     return FALSE;
1225
1226   return g_simple_async_result_get_op_res_gboolean (simple);
1227 }
1228
1229 #ifdef HAVE_PKCS11
1230
1231 static P11KitPin*
1232 on_pin_prompt_callback (const char     *pinfile,
1233                         P11KitUri      *pin_uri,
1234                         const char     *pin_description,
1235                         P11KitPinFlags  pin_flags,
1236                         void           *callback_data)
1237 {
1238   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (callback_data);
1239   GTlsInteractionResult result;
1240   GTlsPasswordFlags flags = 0;
1241   GTlsPassword *password;
1242   P11KitPin *pin = NULL;
1243   GError *error = NULL;
1244
1245   if (!gnutls->priv->interaction)
1246     return NULL;
1247
1248   if (pin_flags & P11_KIT_PIN_FLAGS_RETRY)
1249     flags |= G_TLS_PASSWORD_RETRY;
1250   if (pin_flags & P11_KIT_PIN_FLAGS_MANY_TRIES)
1251     flags |= G_TLS_PASSWORD_MANY_TRIES;
1252   if (pin_flags & P11_KIT_PIN_FLAGS_FINAL_TRY)
1253     flags |= G_TLS_PASSWORD_FINAL_TRY;
1254
1255   password = g_pkcs11_pin_new (flags, pin_description);
1256
1257   result = g_tls_interaction_ask_password (gnutls->priv->interaction, password,
1258                                            g_cancellable_get_current (), &error);
1259
1260   switch (result)
1261     {
1262     case G_TLS_INTERACTION_FAILED:
1263       if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1264         g_warning ("couldn't ask for password: %s", error->message);
1265       pin = NULL;
1266       break;
1267     case G_TLS_INTERACTION_UNHANDLED:
1268       pin = NULL;
1269       break;
1270     case G_TLS_INTERACTION_HANDLED:
1271       pin = g_pkcs11_pin_steal_internal (G_PKCS11_PIN (password));
1272       break;
1273     }
1274
1275   g_object_unref (password);
1276   return pin;
1277 }
1278
1279 #endif /* HAVE_PKCS11 */
1280
1281 static void
1282 g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
1283 {
1284   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1285   GTlsConnectionClass *connection_class = G_TLS_CONNECTION_CLASS (klass);
1286   GIOStreamClass *iostream_class = G_IO_STREAM_CLASS (klass);
1287
1288   g_type_class_add_private (klass, sizeof (GTlsConnectionGnutlsPrivate));
1289
1290   gobject_class->get_property = g_tls_connection_gnutls_get_property;
1291   gobject_class->set_property = g_tls_connection_gnutls_set_property;
1292   gobject_class->finalize     = g_tls_connection_gnutls_finalize;
1293
1294   connection_class->handshake        = g_tls_connection_gnutls_handshake;
1295   connection_class->handshake_async  = g_tls_connection_gnutls_handshake_async;
1296   connection_class->handshake_finish = g_tls_connection_gnutls_handshake_finish;
1297
1298   iostream_class->get_input_stream  = g_tls_connection_gnutls_get_input_stream;
1299   iostream_class->get_output_stream = g_tls_connection_gnutls_get_output_stream;
1300   iostream_class->close_fn          = g_tls_connection_gnutls_close;
1301   iostream_class->close_async       = g_tls_connection_gnutls_close_async;
1302   iostream_class->close_finish      = g_tls_connection_gnutls_close_finish;
1303
1304   g_object_class_override_property (gobject_class, PROP_BASE_IO_STREAM, "base-io-stream");
1305   g_object_class_override_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
1306   g_object_class_override_property (gobject_class, PROP_REHANDSHAKE_MODE, "rehandshake-mode");
1307   g_object_class_override_property (gobject_class, PROP_USE_SYSTEM_CERTDB, "use-system-certdb");
1308   g_object_class_override_property (gobject_class, PROP_DATABASE, "database");
1309   g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
1310   g_object_class_override_property (gobject_class, PROP_INTERACTION, "interaction");
1311   g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE, "peer-certificate");
1312   g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
1313 }
1314
1315 static void
1316 g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface)
1317 {
1318   iface->init = g_tls_connection_gnutls_initable_init;
1319 }