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