ef53bb2a69fb0ebd4348607f5d565d8fcc396b3e
[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 static gboolean do_implicit_handshake (GTlsConnectionGnutls  *gnutls,
64                                        gboolean               blocking,
65                                        GCancellable          *cancellable,
66                                        GError               **error);
67 static gboolean finish_handshake (GTlsConnectionGnutls  *gnutls,
68                                   GTask                 *thread_task,
69                                   GError               **error);
70
71 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GTlsConnectionGnutls, g_tls_connection_gnutls, G_TYPE_TLS_CONNECTION,
72                                   G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
73                                                          g_tls_connection_gnutls_initable_iface_init);
74                                   g_tls_connection_gnutls_init_priorities ();
75                                   );
76
77
78 enum
79 {
80   PROP_0,
81   PROP_BASE_IO_STREAM,
82   PROP_REQUIRE_CLOSE_NOTIFY,
83   PROP_REHANDSHAKE_MODE,
84   PROP_USE_SYSTEM_CERTDB,
85   PROP_DATABASE,
86   PROP_CERTIFICATE,
87   PROP_INTERACTION,
88   PROP_PEER_CERTIFICATE,
89   PROP_PEER_CERTIFICATE_ERRORS
90 };
91
92 struct _GTlsConnectionGnutlsPrivate
93 {
94   GIOStream *base_io_stream;
95   GPollableInputStream *base_istream;
96   GPollableOutputStream *base_ostream;
97
98   gnutls_certificate_credentials creds;
99   gnutls_session session;
100
101   GTlsCertificate *certificate, *peer_certificate;
102   GTlsCertificateFlags peer_certificate_errors;
103   gboolean require_close_notify;
104   GTlsRehandshakeMode rehandshake_mode;
105   gboolean is_system_certdb;
106   GTlsDatabase *database;
107   gboolean database_is_unset;
108
109   /* need_handshake means the next claim_op() will get diverted into
110    * an implicit handshake (unless it's an OP_HANDSHAKE itself).
111    * need_finish_handshake means the next claim_op() will get
112    * diverted into finish_handshake().
113    *
114    * handshaking is TRUE as soon as a handshake thread is queued.
115    * Normally it becomes FALSE after finish_handshake() completes. For
116    * an implicit handshake, but in the case of an async implicit
117    * handshake, it becomes FALSE at the end of handshake_thread(),
118    * (and then the next read/write op will call finish_handshake()).
119    * This is because we don't want to call finish_handshake() (and
120    * possibly emit signals) if the caller is not actually in a TLS op
121    * at the time. (Eg, if they're waiting to try a nonblocking call
122    * again, we don't want to emit the signal until they do.)
123    *
124    * started_handshake indicates that the current handshake attempt
125    * got at least as far as calling gnutls_handshake() (and so any
126    * error should be copied to handshake_error and returned on all
127    * future operations). ever_handshaked indicates that TLS has
128    * been successfully negotiated at some point.
129    */
130   gboolean need_handshake, need_finish_handshake;
131   gboolean started_handshake, handshaking, ever_handshaked;
132   GTask *implicit_handshake;
133   GError *handshake_error;
134
135   gboolean closing, closed;
136
137   GInputStream *tls_istream;
138   GOutputStream *tls_ostream;
139
140   GTlsInteraction *interaction;
141   gchar *interaction_id;
142
143   GMutex        op_mutex;
144   GCancellable *waiting_for_op;
145
146   gboolean      reading;
147   gboolean      read_blocking;
148   GError       *read_error;
149   GCancellable *read_cancellable;
150
151   gboolean      writing;
152   gboolean      write_blocking;
153   GError       *write_error;
154   GCancellable *write_cancellable;
155
156 #ifndef GNUTLS_E_PREMATURE_TERMINATION
157   gboolean eof;
158 #endif
159 };
160
161 static gint unique_interaction_id = 0;
162
163 static void
164 g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
165 {
166   gint unique_id;
167
168   gnutls->priv = G_TYPE_INSTANCE_GET_PRIVATE (gnutls, G_TYPE_TLS_CONNECTION_GNUTLS, GTlsConnectionGnutlsPrivate);
169
170   gnutls_certificate_allocate_credentials (&gnutls->priv->creds);
171   gnutls_certificate_set_verify_flags (gnutls->priv->creds,
172                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
173
174   gnutls->priv->need_handshake = TRUE;
175
176   gnutls->priv->database_is_unset = TRUE;
177   gnutls->priv->is_system_certdb = TRUE;
178
179   unique_id = g_atomic_int_add (&unique_interaction_id, 1);
180   gnutls->priv->interaction_id = g_strdup_printf ("gtls:%d", unique_id);
181
182 #ifdef HAVE_PKCS11
183   p11_kit_pin_register_callback (gnutls->priv->interaction_id,
184                                  on_pin_prompt_callback, gnutls, NULL);
185 #endif
186
187   gnutls->priv->waiting_for_op = g_cancellable_new ();
188   g_cancellable_cancel (gnutls->priv->waiting_for_op);
189 }
190
191 /* First field is "ssl3 only", second is "allow unsafe rehandshaking" */
192 static gnutls_priority_t priorities[2][2];
193
194 static void
195 g_tls_connection_gnutls_init_priorities (void)
196 {
197   const gchar *base_priority;
198   gchar *ssl3_priority, *unsafe_rehandshake_priority, *ssl3_unsafe_rehandshake_priority;
199
200   base_priority = g_getenv ("G_TLS_GNUTLS_PRIORITY");
201   if (!base_priority)
202     base_priority = "NORMAL:%COMPAT";
203
204   ssl3_priority = g_strdup_printf ("%s:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0", base_priority);
205   unsafe_rehandshake_priority = g_strdup_printf ("%s:%%UNSAFE_RENEGOTIATION", base_priority);
206   ssl3_unsafe_rehandshake_priority = g_strdup_printf ("%s:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0:%%UNSAFE_RENEGOTIATION", base_priority);
207
208   gnutls_priority_init (&priorities[FALSE][FALSE], base_priority, NULL);
209   gnutls_priority_init (&priorities[TRUE][FALSE], ssl3_priority, NULL);
210   gnutls_priority_init (&priorities[FALSE][TRUE], unsafe_rehandshake_priority, NULL);
211   gnutls_priority_init (&priorities[TRUE][TRUE], ssl3_unsafe_rehandshake_priority, NULL);
212
213   g_free (ssl3_priority);
214   g_free (unsafe_rehandshake_priority);
215   g_free (ssl3_unsafe_rehandshake_priority);
216 }
217
218 static void
219 g_tls_connection_gnutls_set_handshake_priority (GTlsConnectionGnutls *gnutls)
220 {
221   gboolean use_ssl3, unsafe_rehandshake;
222
223   if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
224     use_ssl3 = g_tls_client_connection_get_use_ssl3 (G_TLS_CLIENT_CONNECTION (gnutls));
225   else
226     use_ssl3 = FALSE;
227   unsafe_rehandshake = (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_UNSAFELY);
228   gnutls_priority_set (gnutls->priv->session,
229                        priorities[use_ssl3][unsafe_rehandshake]);
230 }
231
232 static gboolean
233 g_tls_connection_gnutls_initable_init (GInitable     *initable,
234                                        GCancellable  *cancellable,
235                                        GError       **error)
236 {
237   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (initable);
238   int status;
239
240   g_return_val_if_fail (gnutls->priv->base_istream != NULL &&
241                         gnutls->priv->base_ostream != NULL, FALSE);
242
243   /* Make sure gnutls->priv->session has been initialized (it may have
244    * already been initialized by a construct-time property setter).
245    */
246   g_tls_connection_gnutls_get_session (gnutls);
247
248   status = gnutls_credentials_set (gnutls->priv->session,
249                                    GNUTLS_CRD_CERTIFICATE,
250                                    gnutls->priv->creds);
251   if (status != 0)
252     {
253       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
254                    _("Could not create TLS connection: %s"),
255                    gnutls_strerror (status));
256       return FALSE;
257     }
258
259   /* Some servers (especially on embedded devices) use tiny keys that
260    * gnutls will reject by default. We want it to accept them.
261    */
262   gnutls_dh_set_prime_bits (gnutls->priv->session, 256);
263
264   gnutls_transport_set_push_function (gnutls->priv->session,
265                                       g_tls_connection_gnutls_push_func);
266   gnutls_transport_set_pull_function (gnutls->priv->session,
267                                       g_tls_connection_gnutls_pull_func);
268   gnutls_transport_set_ptr (gnutls->priv->session, gnutls);
269
270   gnutls->priv->tls_istream = g_tls_input_stream_gnutls_new (gnutls);
271   gnutls->priv->tls_ostream = g_tls_output_stream_gnutls_new (gnutls);
272
273   return TRUE;
274 }
275
276 static void
277 g_tls_connection_gnutls_finalize (GObject *object)
278 {
279   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
280
281   g_clear_object (&gnutls->priv->base_io_stream);
282
283   g_clear_object (&gnutls->priv->tls_istream);
284   g_clear_object (&gnutls->priv->tls_ostream);
285
286   if (gnutls->priv->session)
287     gnutls_deinit (gnutls->priv->session);
288   if (gnutls->priv->creds)
289     gnutls_certificate_free_credentials (gnutls->priv->creds);
290
291   g_clear_object (&gnutls->priv->database);
292   g_clear_object (&gnutls->priv->certificate);
293   g_clear_object (&gnutls->priv->peer_certificate);
294
295 #ifdef HAVE_PKCS11
296   p11_kit_pin_unregister_callback (gnutls->priv->interaction_id,
297                                    on_pin_prompt_callback, gnutls);
298 #endif
299   g_free (gnutls->priv->interaction_id);
300   g_clear_object (&gnutls->priv->interaction);
301
302   g_clear_error (&gnutls->priv->handshake_error);
303   g_clear_error (&gnutls->priv->read_error);
304   g_clear_error (&gnutls->priv->write_error);
305
306   g_clear_object (&gnutls->priv->waiting_for_op);
307
308   G_OBJECT_CLASS (g_tls_connection_gnutls_parent_class)->finalize (object);
309 }
310
311 static void
312 g_tls_connection_gnutls_get_property (GObject    *object,
313                                       guint       prop_id,
314                                       GValue     *value,
315                                       GParamSpec *pspec)
316 {
317   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
318   GTlsBackend *backend;
319
320   switch (prop_id)
321     {
322     case PROP_BASE_IO_STREAM:
323       g_value_set_object (value, gnutls->priv->base_io_stream);
324       break;
325
326     case PROP_REQUIRE_CLOSE_NOTIFY:
327       g_value_set_boolean (value, gnutls->priv->require_close_notify);
328       break;
329
330     case PROP_REHANDSHAKE_MODE:
331       g_value_set_enum (value, gnutls->priv->rehandshake_mode);
332       break;
333
334     case PROP_USE_SYSTEM_CERTDB:
335       g_value_set_boolean (value, gnutls->priv->is_system_certdb);
336       break;
337
338     case PROP_DATABASE:
339       if (gnutls->priv->database_is_unset)
340         {
341           backend = g_tls_backend_get_default ();
342           gnutls->priv->database =  g_tls_backend_get_default_database (backend);
343           gnutls->priv->database_is_unset = FALSE;
344         }
345       g_value_set_object (value, gnutls->priv->database);
346       break;
347
348     case PROP_CERTIFICATE:
349       g_value_set_object (value, gnutls->priv->certificate);
350       break;
351
352     case PROP_INTERACTION:
353       g_value_set_object (value, gnutls->priv->interaction);
354       break;
355
356     case PROP_PEER_CERTIFICATE:
357       g_value_set_object (value, gnutls->priv->peer_certificate);
358       break;
359
360     case PROP_PEER_CERTIFICATE_ERRORS:
361       g_value_set_flags (value, gnutls->priv->peer_certificate_errors);
362       break;
363
364     default:
365       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
366     }
367 }
368
369 static void
370 g_tls_connection_gnutls_set_property (GObject      *object,
371                                       guint         prop_id,
372                                       const GValue *value,
373                                       GParamSpec   *pspec)
374 {
375   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
376   GInputStream *istream;
377   GOutputStream *ostream;
378   gboolean system_certdb;
379   GTlsBackend *backend;
380
381   switch (prop_id)
382     {
383     case PROP_BASE_IO_STREAM:
384       if (gnutls->priv->base_io_stream)
385         {
386           g_object_unref (gnutls->priv->base_io_stream);
387           gnutls->priv->base_istream = NULL;
388           gnutls->priv->base_ostream = NULL;
389         }
390       gnutls->priv->base_io_stream = g_value_dup_object (value);
391       if (!gnutls->priv->base_io_stream)
392         return;
393
394       istream = g_io_stream_get_input_stream (gnutls->priv->base_io_stream);
395       ostream = g_io_stream_get_output_stream (gnutls->priv->base_io_stream);
396
397       if (G_IS_POLLABLE_INPUT_STREAM (istream) &&
398           g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (istream)))
399         gnutls->priv->base_istream = G_POLLABLE_INPUT_STREAM (istream);
400       if (G_IS_POLLABLE_OUTPUT_STREAM (ostream) &&
401           g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (ostream)))
402         gnutls->priv->base_ostream = G_POLLABLE_OUTPUT_STREAM (ostream);
403       break;
404
405     case PROP_REQUIRE_CLOSE_NOTIFY:
406       gnutls->priv->require_close_notify = g_value_get_boolean (value);
407       break;
408
409     case PROP_REHANDSHAKE_MODE:
410       gnutls->priv->rehandshake_mode = g_value_get_enum (value);
411       break;
412
413     case PROP_USE_SYSTEM_CERTDB:
414       system_certdb = g_value_get_boolean (value);
415       if (system_certdb != gnutls->priv->is_system_certdb)
416         {
417           g_clear_object (&gnutls->priv->database);
418           if (system_certdb)
419             {
420               backend = g_tls_backend_get_default ();
421               gnutls->priv->database = g_tls_backend_get_default_database (backend);
422             }
423           gnutls->priv->is_system_certdb = system_certdb;
424           gnutls->priv->database_is_unset = FALSE;
425         }
426       break;
427
428     case PROP_DATABASE:
429       g_clear_object (&gnutls->priv->database);
430       gnutls->priv->database = g_value_dup_object (value);
431       gnutls->priv->is_system_certdb = FALSE;
432       gnutls->priv->database_is_unset = FALSE;
433       break;
434
435     case PROP_CERTIFICATE:
436       if (gnutls->priv->certificate)
437         g_object_unref (gnutls->priv->certificate);
438       gnutls->priv->certificate = g_value_dup_object (value);
439       break;
440
441     case PROP_INTERACTION:
442       g_clear_object (&gnutls->priv->interaction);
443       gnutls->priv->interaction = g_value_dup_object (value);
444       break;
445
446     default:
447       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
448     }
449 }
450
451 gnutls_certificate_credentials
452 g_tls_connection_gnutls_get_credentials (GTlsConnectionGnutls *gnutls)
453 {
454   return gnutls->priv->creds;
455 }
456
457 gnutls_session
458 g_tls_connection_gnutls_get_session (GTlsConnectionGnutls *gnutls)
459 {
460   /* Ideally we would initialize gnutls->priv->session from
461    * g_tls_connection_gnutls_init(), but we can't tell if it's a
462    * client or server connection at that point... And
463    * g_tls_connection_gnutls_initiable_init() is too late, because
464    * construct-time property setters may need to modify it.
465    */
466   if (!gnutls->priv->session)
467     {
468       gboolean client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
469       gnutls_init (&gnutls->priv->session, client ? GNUTLS_CLIENT : GNUTLS_SERVER);
470     }
471
472   return gnutls->priv->session;
473 }
474
475 void
476 g_tls_connection_gnutls_get_certificate (GTlsConnectionGnutls *gnutls,
477                                          gnutls_retr2_st      *st)
478 {
479   GTlsCertificate *cert;
480
481   cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (gnutls));
482
483   st->cert_type = GNUTLS_CRT_X509;
484   st->ncerts = 0;
485
486   if (cert)
487       g_tls_certificate_gnutls_copy (G_TLS_CERTIFICATE_GNUTLS (cert),
488                                      gnutls->priv->interaction_id, st);
489 }
490
491 typedef enum {
492   G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE,
493   G_TLS_CONNECTION_GNUTLS_OP_READ,
494   G_TLS_CONNECTION_GNUTLS_OP_WRITE,
495   G_TLS_CONNECTION_GNUTLS_OP_CLOSE,
496 } GTlsConnectionGnutlsOp;
497
498 static gboolean
499 claim_op (GTlsConnectionGnutls    *gnutls,
500           GTlsConnectionGnutlsOp   op,
501           gboolean                 blocking,
502           GCancellable            *cancellable,
503           GError                 **error)
504 {
505  try_again:
506   if (g_cancellable_set_error_if_cancelled (cancellable, error))
507     return FALSE;
508
509   g_mutex_lock (&gnutls->priv->op_mutex);
510
511   if (gnutls->priv->closing || gnutls->priv->closed)
512     {
513       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
514                            _("Connection is closed"));
515       g_mutex_unlock (&gnutls->priv->op_mutex);
516       return FALSE;
517     }
518
519   if (gnutls->priv->handshake_error && op != G_TLS_CONNECTION_GNUTLS_OP_CLOSE)
520     {
521       if (error)
522         *error = g_error_copy (gnutls->priv->handshake_error);
523       g_mutex_unlock (&gnutls->priv->op_mutex);
524       return FALSE;
525     }
526
527   if (op != G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE &&
528       op != G_TLS_CONNECTION_GNUTLS_OP_CLOSE)
529     {
530       if (gnutls->priv->need_handshake)
531         {
532           gnutls->priv->need_handshake = FALSE;
533           gnutls->priv->handshaking = TRUE;
534           if (!do_implicit_handshake (gnutls, blocking, cancellable, error))
535             {
536               g_mutex_unlock (&gnutls->priv->op_mutex);
537               return FALSE;
538             }
539         }
540
541       if (gnutls->priv->need_finish_handshake)
542         {
543           GError *my_error = NULL;
544           gboolean success;
545
546           gnutls->priv->need_finish_handshake = FALSE;
547
548           g_mutex_unlock (&gnutls->priv->op_mutex);
549           success = finish_handshake (gnutls, gnutls->priv->implicit_handshake, &my_error);
550           g_clear_object (&gnutls->priv->implicit_handshake);
551           g_mutex_lock (&gnutls->priv->op_mutex);
552
553           gnutls->priv->handshaking = FALSE;
554           if (!success || g_cancellable_set_error_if_cancelled (cancellable, &my_error))
555             {
556               g_propagate_error (error, my_error);
557               g_mutex_unlock (&gnutls->priv->op_mutex);
558               return FALSE;
559             }
560         }
561     }
562
563   if ((op != G_TLS_CONNECTION_GNUTLS_OP_WRITE && gnutls->priv->reading) ||
564       (op != G_TLS_CONNECTION_GNUTLS_OP_READ && gnutls->priv->writing) ||
565       (op != G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE && gnutls->priv->handshaking))
566     {
567       GPollFD fds[2];
568       int nfds;
569
570       g_cancellable_reset (gnutls->priv->waiting_for_op);
571
572       g_mutex_unlock (&gnutls->priv->op_mutex);
573
574       if (!blocking)
575         {
576           g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
577                                _("Operation would block"));
578           return FALSE;
579         }
580
581       g_cancellable_make_pollfd (gnutls->priv->waiting_for_op, &fds[0]);
582       if (g_cancellable_make_pollfd (cancellable, &fds[0]))
583         nfds = 2;
584       else
585         nfds = 1;
586       g_poll (fds, nfds, -1);
587       g_cancellable_release_fd (cancellable);
588
589       goto try_again;
590     }
591
592   if (op == G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE)
593     {
594       gnutls->priv->handshaking = TRUE;
595       gnutls->priv->need_handshake = FALSE;
596     }
597   if (op == G_TLS_CONNECTION_GNUTLS_OP_CLOSE)
598     gnutls->priv->closing = TRUE;
599
600   if (op != G_TLS_CONNECTION_GNUTLS_OP_WRITE)
601     gnutls->priv->reading = TRUE;
602   if (op != G_TLS_CONNECTION_GNUTLS_OP_READ)
603     gnutls->priv->writing = TRUE;
604
605   g_mutex_unlock (&gnutls->priv->op_mutex);
606   return TRUE;
607 }
608
609 static void
610 yield_op (GTlsConnectionGnutls   *gnutls,
611           GTlsConnectionGnutlsOp  op)
612 {
613   g_mutex_lock (&gnutls->priv->op_mutex);
614
615   if (op == G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE)
616     gnutls->priv->handshaking = FALSE;
617   if (op == G_TLS_CONNECTION_GNUTLS_OP_CLOSE)
618     gnutls->priv->closing = FALSE;
619
620   if (op != G_TLS_CONNECTION_GNUTLS_OP_WRITE)
621     gnutls->priv->reading = FALSE;
622   if (op != G_TLS_CONNECTION_GNUTLS_OP_READ)
623     gnutls->priv->writing = FALSE;
624
625   g_cancellable_cancel (gnutls->priv->waiting_for_op);
626   g_mutex_unlock (&gnutls->priv->op_mutex);
627 }
628
629 static void
630 begin_gnutls_io (GTlsConnectionGnutls  *gnutls,
631                  GIOCondition           direction,
632                  gboolean               blocking,
633                  GCancellable          *cancellable)
634 {
635   g_assert (direction & (G_IO_IN | G_IO_OUT));
636
637   if (direction & G_IO_IN)
638     {
639       gnutls->priv->read_blocking = blocking;
640       gnutls->priv->read_cancellable = cancellable;
641       g_clear_error (&gnutls->priv->read_error);
642     }
643
644   if (direction & G_IO_OUT)
645     {
646       gnutls->priv->write_blocking = blocking;
647       gnutls->priv->write_cancellable = cancellable;
648       g_clear_error (&gnutls->priv->write_error);
649     }
650 }
651
652 static int
653 end_gnutls_io (GTlsConnectionGnutls  *gnutls,
654                GIOCondition           direction,
655                int                    status,
656                const char            *errmsg,
657                GError               **error)
658 {
659   GError *my_error = NULL;
660
661   g_assert (direction & (G_IO_IN | G_IO_OUT));
662   g_assert (!error || !*error);
663
664   if (status == GNUTLS_E_AGAIN ||
665       status == GNUTLS_E_WARNING_ALERT_RECEIVED)
666     return GNUTLS_E_AGAIN;
667
668   if (direction & G_IO_IN)
669     {
670       gnutls->priv->read_cancellable = NULL;
671       if (status < 0)
672         {
673           my_error = gnutls->priv->read_error;
674           gnutls->priv->read_error = NULL;
675         }
676       else
677         g_clear_error (&gnutls->priv->read_error);
678     }
679   if (direction & G_IO_OUT)
680     {
681       gnutls->priv->write_cancellable = NULL;
682       if (status < 0 && !my_error)
683         {
684           my_error = gnutls->priv->write_error;
685           gnutls->priv->write_error = NULL;
686         }
687       else
688         g_clear_error (&gnutls->priv->write_error);
689     }
690
691   if (status >= 0)
692     return status;
693
694   if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
695     {
696       if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
697 #if GLIB_CHECK_VERSION (2, 35, 3)
698           g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE) ||
699 #endif
700           status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH ||
701           status == GNUTLS_E_FATAL_ALERT_RECEIVED ||
702           status == GNUTLS_E_DECRYPTION_FAILED ||
703           status == GNUTLS_E_UNSUPPORTED_VERSION_PACKET)
704         {
705           g_clear_error (&my_error);
706           g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS,
707                                _("Peer failed to perform TLS handshake"));
708           return GNUTLS_E_PULL_ERROR;
709         }
710     }
711
712   if (my_error)
713     {
714       if (!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
715         G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->failed (gnutls);
716       g_propagate_error (error, my_error);
717       return status;
718     }
719   else if (status == GNUTLS_E_REHANDSHAKE)
720     {
721       if (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_NEVER)
722         {
723           g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
724                                _("Peer requested illegal TLS rehandshake"));
725           return GNUTLS_E_PULL_ERROR;
726         }
727
728       g_mutex_lock (&gnutls->priv->op_mutex);
729       if (!gnutls->priv->handshaking)
730         gnutls->priv->need_handshake = TRUE;
731       g_mutex_unlock (&gnutls->priv->op_mutex);
732       return status;
733     }
734   else if (status == GNUTLS_E_GOT_APPLICATION_DATA)
735     {
736       if (gnutls->priv->handshaking && G_IS_TLS_SERVER_CONNECTION (gnutls))
737         return GNUTLS_E_AGAIN;
738     }
739   else if (
740 #ifdef GNUTLS_E_PREMATURE_TERMINATION
741            status == GNUTLS_E_PREMATURE_TERMINATION
742 #else
743            status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH && gnutls->priv->eof
744 #endif
745            )
746     {
747       if (gnutls->priv->require_close_notify)
748         {
749           g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_EOF,
750                                _("TLS connection closed unexpectedly"));
751           G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->failed (gnutls);
752           return status;
753         }
754       else
755         return 0;
756     }
757   else if (status == GNUTLS_E_NO_CERTIFICATE_FOUND)
758     {
759       g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED,
760                            _("TLS connection peer did not send a certificate"));
761       return status;
762     }
763
764   if (error)
765     {
766       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
767                    errmsg, gnutls_strerror (status));
768     }
769   return status;
770 }
771
772 #define BEGIN_GNUTLS_IO(gnutls, direction, blocking, cancellable)       \
773   begin_gnutls_io (gnutls, direction, blocking, cancellable);           \
774   do {
775
776 #define END_GNUTLS_IO(gnutls, direction, ret, errmsg, err)              \
777   } while ((ret = end_gnutls_io (gnutls, direction, ret, errmsg, err)) == GNUTLS_E_AGAIN);
778
779 gboolean
780 g_tls_connection_gnutls_check (GTlsConnectionGnutls  *gnutls,
781                                GIOCondition           condition)
782 {
783   /* Racy, but worst case is that we just get WOULD_BLOCK back */
784   if (gnutls->priv->need_finish_handshake)
785     return TRUE;
786
787   /* If a handshake or close is in progress, then tls_istream and
788    * tls_ostream are blocked, regardless of the base stream status.
789    */
790   if (gnutls->priv->handshaking || gnutls->priv->closing)
791     return FALSE;
792
793   if (condition & G_IO_IN)
794     return g_pollable_input_stream_is_readable (gnutls->priv->base_istream);
795   else
796     return g_pollable_output_stream_is_writable (gnutls->priv->base_ostream);
797 }
798
799 typedef struct {
800   GSource               source;
801
802   GTlsConnectionGnutls *gnutls;
803   GObject              *stream;
804
805   GSource              *child_source;
806   GIOCondition          condition;
807
808   gboolean              io_waiting;
809   gboolean              op_waiting;
810 } GTlsConnectionGnutlsSource;
811
812 static gboolean
813 gnutls_source_prepare (GSource *source,
814                        gint    *timeout)
815 {
816   *timeout = -1;
817   return FALSE;
818 }
819
820 static gboolean
821 gnutls_source_check (GSource *source)
822 {
823   return FALSE;
824 }
825
826 static void
827 gnutls_source_sync (GTlsConnectionGnutlsSource *gnutls_source)
828 {
829   GTlsConnectionGnutls *gnutls = gnutls_source->gnutls;
830   gboolean io_waiting, op_waiting;
831
832   g_mutex_lock (&gnutls->priv->op_mutex);
833   if (((gnutls_source->condition & G_IO_IN) && gnutls->priv->reading) ||
834       ((gnutls_source->condition & G_IO_OUT) && gnutls->priv->writing) ||
835       (gnutls->priv->handshaking && !gnutls->priv->need_finish_handshake))
836     op_waiting = TRUE;
837   else
838     op_waiting = FALSE;
839
840   if (!op_waiting && !gnutls->priv->need_handshake &&
841       !gnutls->priv->need_finish_handshake)
842     io_waiting = TRUE;
843   else
844     io_waiting = FALSE;
845   g_mutex_unlock (&gnutls->priv->op_mutex);
846
847   if (op_waiting == gnutls_source->op_waiting &&
848       io_waiting == gnutls_source->io_waiting)
849     return;
850   gnutls_source->op_waiting = op_waiting;
851   gnutls_source->io_waiting = io_waiting;
852
853   if (gnutls_source->child_source)
854     {
855       g_source_remove_child_source ((GSource *)gnutls_source,
856                                     gnutls_source->child_source);
857       g_source_unref (gnutls_source->child_source);
858     }
859
860   if (op_waiting)
861     gnutls_source->child_source = g_cancellable_source_new (gnutls->priv->waiting_for_op);
862   else if (io_waiting && G_IS_POLLABLE_INPUT_STREAM (gnutls_source->stream))
863     gnutls_source->child_source = g_pollable_input_stream_create_source (gnutls->priv->base_istream, NULL);
864   else if (io_waiting && G_IS_POLLABLE_OUTPUT_STREAM (gnutls_source->stream))
865     gnutls_source->child_source = g_pollable_output_stream_create_source (gnutls->priv->base_ostream, NULL);
866   else
867     gnutls_source->child_source = g_timeout_source_new (0);
868
869   g_source_set_dummy_callback (gnutls_source->child_source);
870   g_source_add_child_source ((GSource *)gnutls_source, gnutls_source->child_source);
871 }
872
873 static gboolean
874 gnutls_source_dispatch (GSource     *source,
875                         GSourceFunc  callback,
876                         gpointer     user_data)
877 {
878   GPollableSourceFunc func = (GPollableSourceFunc)callback;
879   GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
880   gboolean ret;
881
882   ret = (*func) (gnutls_source->stream, user_data);
883   if (ret)
884     gnutls_source_sync (gnutls_source);
885
886   return ret;
887 }
888
889 static void
890 gnutls_source_finalize (GSource *source)
891 {
892   GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
893
894   g_object_unref (gnutls_source->gnutls);
895   g_source_unref (gnutls_source->child_source);
896 }
897
898 static gboolean
899 g_tls_connection_gnutls_source_closure_callback (GObject  *stream,
900                                                  gpointer  data)
901 {
902   GClosure *closure = data;
903
904   GValue param = { 0, };
905   GValue result_value = { 0, };
906   gboolean result;
907
908   g_value_init (&result_value, G_TYPE_BOOLEAN);
909
910   g_value_init (&param, G_TYPE_OBJECT);
911   g_value_set_object (&param, stream);
912
913   g_closure_invoke (closure, &result_value, 1, &param, NULL);
914
915   result = g_value_get_boolean (&result_value);
916   g_value_unset (&result_value);
917   g_value_unset (&param);
918
919   return result;
920 }
921
922 static GSourceFuncs gnutls_source_funcs =
923 {
924   gnutls_source_prepare,
925   gnutls_source_check,
926   gnutls_source_dispatch,
927   gnutls_source_finalize,
928   (GSourceFunc)g_tls_connection_gnutls_source_closure_callback,
929   (GSourceDummyMarshal)g_cclosure_marshal_generic
930 };
931
932 GSource *
933 g_tls_connection_gnutls_create_source (GTlsConnectionGnutls  *gnutls,
934                                        GIOCondition           condition,
935                                        GCancellable          *cancellable)
936 {
937   GSource *source, *cancellable_source;
938   GTlsConnectionGnutlsSource *gnutls_source;
939
940   source = g_source_new (&gnutls_source_funcs, sizeof (GTlsConnectionGnutlsSource));
941   g_source_set_name (source, "GTlsConnectionGnutlsSource");
942   gnutls_source = (GTlsConnectionGnutlsSource *)source;
943   gnutls_source->gnutls = g_object_ref (gnutls);
944   gnutls_source->condition = condition;
945   if (condition & G_IO_IN)
946     gnutls_source->stream = G_OBJECT (gnutls->priv->tls_istream);
947   else if (condition & G_IO_OUT)
948     gnutls_source->stream = G_OBJECT (gnutls->priv->tls_ostream);
949
950   gnutls_source->op_waiting = (gboolean) -1;
951   gnutls_source->io_waiting = (gboolean) -1;
952   gnutls_source_sync (gnutls_source);
953
954   if (cancellable)
955     {
956       cancellable_source = g_cancellable_source_new (cancellable);
957       g_source_set_dummy_callback (cancellable_source);
958       g_source_add_child_source (source, cancellable_source);
959       g_source_unref (cancellable_source);
960     }
961
962   return source;
963 }
964
965 static void
966 set_gnutls_error (GTlsConnectionGnutls *gnutls,
967                   GError               *error)
968 {
969   /* We set EINTR rather than EAGAIN for G_IO_ERROR_WOULD_BLOCK so
970    * that GNUTLS_E_AGAIN only gets returned for gnutls-internal
971    * reasons, not for actual socket EAGAINs (and we have access
972    * to @error at the higher levels, so we can distinguish them
973    * that way later).
974    */
975
976   if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
977     gnutls_transport_set_errno (gnutls->priv->session, EINTR);
978   else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
979     gnutls_transport_set_errno (gnutls->priv->session, EINTR);
980   else
981     gnutls_transport_set_errno (gnutls->priv->session, EIO);
982 }
983
984 static ssize_t
985 g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t  transport_data,
986                                    void                   *buf,
987                                    size_t                  buflen)
988 {
989   GTlsConnectionGnutls *gnutls = transport_data;
990   ssize_t ret;
991
992   /* If gnutls->priv->read_error is non-%NULL when we're called, it means
993    * that an error previously occurred, but gnutls decided not to
994    * propagate it. So it's correct for us to just clear it. (Usually
995    * this means it ignored an EAGAIN after a short read, and now
996    * we'll return EAGAIN again, which it will obey this time.)
997    */
998   g_clear_error (&gnutls->priv->read_error);
999
1000   ret = g_pollable_stream_read (G_INPUT_STREAM (gnutls->priv->base_istream),
1001                                 buf, buflen,
1002                                 gnutls->priv->read_blocking,
1003                                 gnutls->priv->read_cancellable,
1004                                 &gnutls->priv->read_error);
1005
1006   if (ret < 0)
1007     set_gnutls_error (gnutls, gnutls->priv->read_error);
1008 #ifndef GNUTLS_E_PREMATURE_TERMINATION
1009   else if (ret == 0)
1010     gnutls->priv->eof = TRUE;
1011 #endif
1012
1013   return ret;
1014 }
1015
1016 static ssize_t
1017 g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t  transport_data,
1018                                    const void             *buf,
1019                                    size_t                  buflen)
1020 {
1021   GTlsConnectionGnutls *gnutls = transport_data;
1022   ssize_t ret;
1023
1024   /* See comment in pull_func. */
1025   g_clear_error (&gnutls->priv->write_error);
1026
1027   ret = g_pollable_stream_write (G_OUTPUT_STREAM (gnutls->priv->base_ostream),
1028                                  buf, buflen,
1029                                  gnutls->priv->write_blocking,
1030                                  gnutls->priv->write_cancellable,
1031                                  &gnutls->priv->write_error);
1032   if (ret < 0)
1033     set_gnutls_error (gnutls, gnutls->priv->write_error);
1034
1035   return ret;
1036 }
1037
1038 static void
1039 handshake_thread (GTask        *task,
1040                   gpointer      object,
1041                   gpointer      task_data,
1042                   GCancellable *cancellable)
1043 {
1044   GTlsConnectionGnutls *gnutls = object;
1045   gboolean is_client;
1046   GError *error = NULL;
1047   int ret;
1048
1049   gnutls->priv->started_handshake = FALSE;
1050
1051   if (!claim_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE,
1052                  TRUE, cancellable, &error))
1053     {
1054       g_task_return_error (task, error);
1055       return;
1056     }
1057
1058   g_clear_error (&gnutls->priv->handshake_error);
1059
1060   is_client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
1061
1062   if (!is_client && gnutls->priv->ever_handshaked &&
1063       !gnutls->priv->implicit_handshake)
1064     {
1065       BEGIN_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, TRUE, cancellable);
1066       ret = gnutls_rehandshake (gnutls->priv->session);
1067       END_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, ret,
1068                      _("Error performing TLS handshake: %s"), &error);
1069
1070       if (error)
1071         {
1072           g_task_return_error (task, error);
1073           return;
1074         }
1075     }
1076
1077   gnutls->priv->started_handshake = TRUE;
1078
1079   g_clear_object (&gnutls->priv->peer_certificate);
1080   gnutls->priv->peer_certificate_errors = 0;
1081
1082   g_tls_connection_gnutls_set_handshake_priority (gnutls);
1083
1084   BEGIN_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, TRUE, cancellable);
1085   ret = gnutls_handshake (gnutls->priv->session);
1086   END_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, ret,
1087                  _("Error performing TLS handshake: %s"), &error);
1088
1089   if (error)
1090     {
1091       g_task_return_error (task, error);
1092     }
1093   else
1094     {
1095       gnutls->priv->ever_handshaked = TRUE;
1096       g_task_return_boolean (task, TRUE);
1097     }
1098 }
1099
1100 static GTlsCertificate *
1101 get_peer_certificate_from_session (GTlsConnectionGnutls *gnutls)
1102 {
1103   GTlsCertificate *chain, *cert;
1104   const gnutls_datum_t *certs;
1105   unsigned int num_certs;
1106   int i;
1107
1108   certs = gnutls_certificate_get_peers (gnutls->priv->session, &num_certs);
1109   if (!certs || !num_certs)
1110     return NULL;
1111
1112   chain = NULL;
1113   for (i = num_certs - 1; i >= 0; i--)
1114     {
1115       cert = g_tls_certificate_gnutls_new (&certs[i], chain);
1116       if (chain)
1117         g_object_unref (chain);
1118       chain = cert;
1119     }
1120
1121   return chain;
1122 }
1123
1124 static GTlsCertificateFlags
1125 verify_peer_certificate (GTlsConnectionGnutls *gnutls,
1126                          GTlsCertificate      *peer_certificate)
1127 {
1128   GTlsConnection *conn = G_TLS_CONNECTION (gnutls);
1129   GSocketConnectable *peer_identity;
1130   GTlsDatabase *database;
1131   GTlsCertificateFlags errors;
1132   gboolean is_client;
1133
1134   is_client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
1135   if (is_client)
1136     peer_identity = g_tls_client_connection_get_server_identity (G_TLS_CLIENT_CONNECTION (gnutls));
1137   else
1138     peer_identity = NULL;
1139
1140   errors = 0;
1141
1142   database = g_tls_connection_get_database (conn);
1143   if (database == NULL)
1144     {
1145       errors |= G_TLS_CERTIFICATE_UNKNOWN_CA;
1146       errors |= g_tls_certificate_verify (peer_certificate, peer_identity, NULL);
1147     }
1148   else
1149     {
1150       GError *error = NULL;
1151
1152       errors |= g_tls_database_verify_chain (database, peer_certificate,
1153                                              is_client ?
1154                                              G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER :
1155                                              G_TLS_DATABASE_PURPOSE_AUTHENTICATE_CLIENT,
1156                                              peer_identity,
1157                                              g_tls_connection_get_interaction (conn),
1158                                              G_TLS_DATABASE_VERIFY_NONE,
1159                                              NULL, &error);
1160       if (error)
1161         {
1162           g_warning ("failure verifying certificate chain: %s",
1163                      error->message);
1164           g_assert (errors != 0);
1165           g_clear_error (&error);
1166         }
1167     }
1168
1169   return errors;
1170 }
1171
1172 static gboolean
1173 accept_peer_certificate (GTlsConnectionGnutls *gnutls,
1174                          GTlsCertificate      *peer_certificate,
1175                          GTlsCertificateFlags  peer_certificate_errors)
1176 {
1177   gboolean accepted;
1178
1179   if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
1180     {
1181       GTlsCertificateFlags validation_flags =
1182         g_tls_client_connection_get_validation_flags (G_TLS_CLIENT_CONNECTION (gnutls));
1183
1184       if ((peer_certificate_errors & validation_flags) == 0)
1185         accepted = TRUE;
1186       else
1187         {
1188           accepted = g_tls_connection_emit_accept_certificate (G_TLS_CONNECTION (gnutls),
1189                                                                peer_certificate,
1190                                                                peer_certificate_errors);
1191         }
1192     }
1193   else
1194     {
1195       accepted = g_tls_connection_emit_accept_certificate (G_TLS_CONNECTION (gnutls),
1196                                                            peer_certificate,
1197                                                            peer_certificate_errors);
1198     }
1199
1200   return accepted;
1201 }
1202
1203 static void
1204 begin_handshake (GTlsConnectionGnutls *gnutls)
1205 {
1206   G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->begin_handshake (gnutls);
1207 }
1208
1209 static gboolean
1210 finish_handshake (GTlsConnectionGnutls  *gnutls,
1211                   GTask                 *task,
1212                   GError               **error)
1213 {
1214   GTlsCertificate *peer_certificate;
1215   GTlsCertificateFlags peer_certificate_errors;
1216
1217   g_assert (error != NULL);
1218
1219   if (g_task_propagate_boolean (task, error) &&
1220       gnutls_certificate_type_get (gnutls->priv->session) == GNUTLS_CRT_X509)
1221     peer_certificate = get_peer_certificate_from_session (gnutls);
1222   else
1223     peer_certificate = NULL;
1224
1225   if (peer_certificate)
1226     {
1227       peer_certificate_errors = verify_peer_certificate (gnutls, peer_certificate);
1228       if (!accept_peer_certificate (gnutls, peer_certificate,
1229                                     peer_certificate_errors))
1230         {
1231           g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
1232                                _("Unacceptable TLS certificate"));
1233         }
1234
1235       gnutls->priv->peer_certificate = peer_certificate;
1236       gnutls->priv->peer_certificate_errors = peer_certificate_errors;
1237       g_object_notify (G_OBJECT (gnutls), "peer-certificate");
1238       g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
1239     }
1240   else if (error && !*error && G_IS_TLS_CLIENT_CONNECTION (gnutls))
1241     {
1242       g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
1243                            _("Server did not return a valid TLS certificate"));
1244     }
1245
1246   G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->finish_handshake (gnutls, error);
1247
1248   if (*error && gnutls->priv->started_handshake)
1249     gnutls->priv->handshake_error = g_error_copy (*error);
1250
1251   return (*error == NULL);
1252 }
1253
1254 static gboolean
1255 g_tls_connection_gnutls_handshake (GTlsConnection   *conn,
1256                                    GCancellable     *cancellable,
1257                                    GError          **error)
1258 {
1259   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
1260   GTask *task;
1261   gboolean success;
1262   GError *my_error = NULL;
1263
1264   task = g_task_new (conn, cancellable, NULL, NULL);
1265   begin_handshake (gnutls);
1266   g_task_run_in_thread_sync (task, handshake_thread);
1267   success = finish_handshake (gnutls, task, &my_error);
1268   g_object_unref (task);
1269
1270   yield_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE);
1271
1272   if (my_error)
1273     g_propagate_error (error, my_error);
1274   return success;
1275 }
1276
1277 /* In the async version we use two GTasks; one to run handshake_thread() and
1278  * then call handshake_thread_completed(), and a second to call the caller's
1279  * original callback after we call finish_handshake().
1280  */
1281
1282 static void
1283 handshake_thread_completed (GObject      *object,
1284                             GAsyncResult *result,
1285                             gpointer      user_data)
1286 {
1287   GTask *caller_task = user_data;
1288   GTlsConnectionGnutls *gnutls = g_task_get_source_object (caller_task);
1289   GError *error = NULL;
1290   gboolean success;
1291
1292   success = finish_handshake (gnutls, G_TASK (result), &error);
1293   yield_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE);
1294
1295   if (success)
1296     g_task_return_boolean (caller_task, TRUE);
1297   else
1298     g_task_return_error (caller_task, error);
1299   g_object_unref (caller_task);
1300 }
1301
1302 static void
1303 g_tls_connection_gnutls_handshake_async (GTlsConnection       *conn,
1304                                          int                   io_priority,
1305                                          GCancellable         *cancellable,
1306                                          GAsyncReadyCallback   callback,
1307                                          gpointer              user_data)
1308 {
1309   GTask *thread_task, *caller_task;
1310
1311   caller_task = g_task_new (conn, cancellable, callback, user_data);
1312   g_task_set_priority (caller_task, io_priority);
1313
1314   begin_handshake (G_TLS_CONNECTION_GNUTLS (conn));
1315
1316   thread_task = g_task_new (conn, cancellable,
1317                             handshake_thread_completed, caller_task);
1318   g_task_set_priority (thread_task, io_priority);
1319   g_task_run_in_thread (thread_task, handshake_thread);
1320   g_object_unref (thread_task);
1321 }
1322
1323 static gboolean
1324 g_tls_connection_gnutls_handshake_finish (GTlsConnection       *conn,
1325                                           GAsyncResult         *result,
1326                                           GError              **error)
1327 {
1328   g_return_val_if_fail (g_task_is_valid (result, conn), FALSE);
1329
1330   return g_task_propagate_boolean (G_TASK (result), error);
1331 }
1332
1333 static void
1334 implicit_handshake_completed (GObject      *object,
1335                               GAsyncResult *result,
1336                               gpointer      user_data)
1337 {
1338   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
1339
1340   g_mutex_lock (&gnutls->priv->op_mutex);
1341   gnutls->priv->need_finish_handshake = TRUE;
1342   g_mutex_unlock (&gnutls->priv->op_mutex);
1343
1344   yield_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE);
1345 }
1346
1347 static gboolean
1348 do_implicit_handshake (GTlsConnectionGnutls  *gnutls,
1349                        gboolean               blocking,
1350                        GCancellable          *cancellable,
1351                        GError               **error)
1352 {
1353   /* We have op_mutex */
1354
1355   gnutls->priv->implicit_handshake = g_task_new (gnutls, cancellable,
1356                                                  implicit_handshake_completed,
1357                                                  NULL);
1358
1359   begin_handshake (gnutls);
1360
1361   if (blocking)
1362     {
1363       GError *my_error = NULL;
1364       gboolean success;
1365
1366       g_mutex_unlock (&gnutls->priv->op_mutex);
1367       g_task_run_in_thread_sync (gnutls->priv->implicit_handshake,
1368                                  handshake_thread);
1369       success = finish_handshake (gnutls,
1370                                   gnutls->priv->implicit_handshake,
1371                                   &my_error);
1372       g_clear_object (&gnutls->priv->implicit_handshake);
1373       yield_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE);
1374       g_mutex_lock (&gnutls->priv->op_mutex);
1375
1376       if (my_error)
1377         g_propagate_error (error, my_error);
1378       return success;
1379     }
1380   else
1381     {
1382       g_task_run_in_thread (gnutls->priv->implicit_handshake,
1383                             handshake_thread);
1384
1385       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
1386                            _("Operation would block"));
1387
1388       return FALSE;
1389     }
1390 }
1391
1392 gssize
1393 g_tls_connection_gnutls_read (GTlsConnectionGnutls  *gnutls,
1394                               void                  *buffer,
1395                               gsize                  count,
1396                               gboolean               blocking,
1397                               GCancellable          *cancellable,
1398                               GError               **error)
1399 {
1400   gssize ret;
1401
1402  again:
1403   if (!claim_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_READ,
1404                  blocking, cancellable, error))
1405     return -1;
1406
1407   BEGIN_GNUTLS_IO (gnutls, G_IO_IN, blocking, cancellable);
1408   ret = gnutls_record_recv (gnutls->priv->session, buffer, count);
1409   END_GNUTLS_IO (gnutls, G_IO_IN, ret, _("Error reading data from TLS socket: %s"), error);
1410
1411   yield_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_READ);
1412
1413   if (ret >= 0)
1414     return ret;
1415   else if (ret == GNUTLS_E_REHANDSHAKE)
1416     goto again;
1417   else
1418     return -1;
1419 }
1420
1421 gssize
1422 g_tls_connection_gnutls_write (GTlsConnectionGnutls  *gnutls,
1423                                const void            *buffer,
1424                                gsize                  count,
1425                                gboolean               blocking,
1426                                GCancellable          *cancellable,
1427                                GError               **error)
1428 {
1429   gssize ret;
1430
1431  again:
1432   if (!claim_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_WRITE,
1433                  blocking, cancellable, error))
1434     return -1;
1435
1436   BEGIN_GNUTLS_IO (gnutls, G_IO_OUT, blocking, cancellable);
1437   ret = gnutls_record_send (gnutls->priv->session, buffer, count);
1438   END_GNUTLS_IO (gnutls, G_IO_OUT, ret, _("Error writing data to TLS socket: %s"), error);
1439
1440   yield_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_WRITE);
1441
1442   if (ret >= 0)
1443     return ret;
1444   else if (ret == GNUTLS_E_REHANDSHAKE)
1445     goto again;
1446   else
1447     return -1;
1448 }
1449
1450 static GInputStream  *
1451 g_tls_connection_gnutls_get_input_stream (GIOStream *stream)
1452 {
1453   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1454
1455   return gnutls->priv->tls_istream;
1456 }
1457
1458 static GOutputStream *
1459 g_tls_connection_gnutls_get_output_stream (GIOStream *stream)
1460 {
1461   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1462
1463   return gnutls->priv->tls_ostream;
1464 }
1465
1466 static gboolean
1467 g_tls_connection_gnutls_close (GIOStream     *stream,
1468                                GCancellable  *cancellable,
1469                                GError       **error)
1470 {
1471   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1472   gboolean success;
1473   int ret = 0;
1474
1475   if (!claim_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_CLOSE,
1476                  TRUE, cancellable, error))
1477     return FALSE;
1478
1479   if (gnutls->priv->closed)
1480     {
1481       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
1482                            _("Connection is already closed"));
1483       yield_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_CLOSE);
1484       return FALSE;
1485     }
1486
1487   if (gnutls->priv->ever_handshaked)
1488     {
1489       BEGIN_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, TRUE, cancellable);
1490       ret = gnutls_bye (gnutls->priv->session, GNUTLS_SHUT_WR);
1491       END_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, ret,
1492                      _("Error performing TLS close: %s"), error);
1493     }
1494
1495   gnutls->priv->closed = TRUE;
1496
1497   if (ret != 0)
1498     {
1499       yield_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_CLOSE);
1500       return FALSE;
1501     }
1502
1503   success = g_io_stream_close (gnutls->priv->base_io_stream,
1504                                cancellable, error);
1505   yield_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_CLOSE);
1506   return success;
1507 }
1508
1509 /* We do async close as synchronous-in-a-thread so we don't need to
1510  * implement G_IO_IN/G_IO_OUT flip-flopping just for this one case
1511  * (since handshakes are also done synchronously now).
1512  */
1513 static void
1514 close_thread (GTask        *task,
1515               gpointer      object,
1516               gpointer      task_data,
1517               GCancellable *cancellable)
1518 {
1519   GIOStream *stream = object;
1520   GError *error = NULL;
1521
1522   if (!g_tls_connection_gnutls_close (stream, cancellable, &error))
1523     g_task_return_error (task, error);
1524   else
1525     g_task_return_boolean (task, TRUE);
1526 }
1527
1528 static void
1529 g_tls_connection_gnutls_close_async (GIOStream           *stream,
1530                                      int                  io_priority,
1531                                      GCancellable        *cancellable,
1532                                      GAsyncReadyCallback  callback,
1533                                      gpointer             user_data)
1534 {
1535   GTask *task;
1536
1537   task = g_task_new (stream, cancellable, callback, user_data);
1538   g_task_set_priority (task, io_priority);
1539   g_task_run_in_thread (task, close_thread);
1540   g_object_unref (task);
1541 }
1542
1543 static gboolean
1544 g_tls_connection_gnutls_close_finish (GIOStream           *stream,
1545                                       GAsyncResult        *result,
1546                                       GError             **error)
1547 {
1548   g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
1549
1550   return g_task_propagate_boolean (G_TASK (result), error);
1551 }
1552
1553 #ifdef HAVE_PKCS11
1554
1555 static P11KitPin*
1556 on_pin_prompt_callback (const char     *pinfile,
1557                         P11KitUri      *pin_uri,
1558                         const char     *pin_description,
1559                         P11KitPinFlags  pin_flags,
1560                         void           *callback_data)
1561 {
1562   GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (callback_data);
1563   GTlsInteractionResult result;
1564   GTlsPasswordFlags flags = 0;
1565   GTlsPassword *password;
1566   P11KitPin *pin = NULL;
1567   GError *error = NULL;
1568
1569   if (!gnutls->priv->interaction)
1570     return NULL;
1571
1572   if (pin_flags & P11_KIT_PIN_FLAGS_RETRY)
1573     flags |= G_TLS_PASSWORD_RETRY;
1574   if (pin_flags & P11_KIT_PIN_FLAGS_MANY_TRIES)
1575     flags |= G_TLS_PASSWORD_MANY_TRIES;
1576   if (pin_flags & P11_KIT_PIN_FLAGS_FINAL_TRY)
1577     flags |= G_TLS_PASSWORD_FINAL_TRY;
1578
1579   password = g_pkcs11_pin_new (flags, pin_description);
1580
1581   result = g_tls_interaction_ask_password (gnutls->priv->interaction, password,
1582                                            g_cancellable_get_current (), &error);
1583
1584   switch (result)
1585     {
1586     case G_TLS_INTERACTION_FAILED:
1587       if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1588         g_warning ("couldn't ask for password: %s", error->message);
1589       pin = NULL;
1590       break;
1591     case G_TLS_INTERACTION_UNHANDLED:
1592       pin = NULL;
1593       break;
1594     case G_TLS_INTERACTION_HANDLED:
1595       pin = g_pkcs11_pin_steal_internal (G_PKCS11_PIN (password));
1596       break;
1597     }
1598
1599   g_object_unref (password);
1600   return pin;
1601 }
1602
1603 #endif /* HAVE_PKCS11 */
1604
1605 static void
1606 g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
1607 {
1608   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1609   GTlsConnectionClass *connection_class = G_TLS_CONNECTION_CLASS (klass);
1610   GIOStreamClass *iostream_class = G_IO_STREAM_CLASS (klass);
1611
1612   g_type_class_add_private (klass, sizeof (GTlsConnectionGnutlsPrivate));
1613
1614   gobject_class->get_property = g_tls_connection_gnutls_get_property;
1615   gobject_class->set_property = g_tls_connection_gnutls_set_property;
1616   gobject_class->finalize     = g_tls_connection_gnutls_finalize;
1617
1618   connection_class->handshake        = g_tls_connection_gnutls_handshake;
1619   connection_class->handshake_async  = g_tls_connection_gnutls_handshake_async;
1620   connection_class->handshake_finish = g_tls_connection_gnutls_handshake_finish;
1621
1622   iostream_class->get_input_stream  = g_tls_connection_gnutls_get_input_stream;
1623   iostream_class->get_output_stream = g_tls_connection_gnutls_get_output_stream;
1624   iostream_class->close_fn          = g_tls_connection_gnutls_close;
1625   iostream_class->close_async       = g_tls_connection_gnutls_close_async;
1626   iostream_class->close_finish      = g_tls_connection_gnutls_close_finish;
1627
1628   g_object_class_override_property (gobject_class, PROP_BASE_IO_STREAM, "base-io-stream");
1629   g_object_class_override_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
1630   g_object_class_override_property (gobject_class, PROP_REHANDSHAKE_MODE, "rehandshake-mode");
1631   g_object_class_override_property (gobject_class, PROP_USE_SYSTEM_CERTDB, "use-system-certdb");
1632   g_object_class_override_property (gobject_class, PROP_DATABASE, "database");
1633   g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
1634   g_object_class_override_property (gobject_class, PROP_INTERACTION, "interaction");
1635   g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE, "peer-certificate");
1636   g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
1637 }
1638
1639 static void
1640 g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface)
1641 {
1642   iface->init = g_tls_connection_gnutls_initable_init;
1643 }