1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright 2010 Red Hat, Inc
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.
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.
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/>.
24 #include <gnutls/gnutls.h>
25 #include <gnutls/x509.h>
27 #include "gtlsserverconnection-gnutls.h"
28 #include "gtlsbackend-gnutls.h"
29 #include "gtlscertificate-gnutls.h"
30 #include <glib/gi18n-lib.h>
35 PROP_AUTHENTICATION_MODE
38 static void g_tls_server_connection_gnutls_initable_interface_init (GInitableIface *iface);
40 static void g_tls_server_connection_gnutls_server_connection_interface_init (GTlsServerConnectionInterface *iface);
42 static int g_tls_server_connection_gnutls_retrieve_function (gnutls_session_t session,
43 const gnutls_datum_t *req_ca_rdn,
45 const gnutls_pk_algorithm_t *pk_algos,
49 static int g_tls_server_connection_gnutls_db_store (void *user_data,
52 static int g_tls_server_connection_gnutls_db_remove (void *user_data,
54 static gnutls_datum_t g_tls_server_connection_gnutls_db_retrieve (void *user_data,
57 static GInitableIface *g_tls_server_connection_gnutls_parent_initable_iface;
59 G_DEFINE_TYPE_WITH_CODE (GTlsServerConnectionGnutls, g_tls_server_connection_gnutls, G_TYPE_TLS_CONNECTION_GNUTLS,
60 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
61 g_tls_server_connection_gnutls_initable_interface_init)
62 G_IMPLEMENT_INTERFACE (G_TYPE_TLS_SERVER_CONNECTION,
63 g_tls_server_connection_gnutls_server_connection_interface_init)
66 struct _GTlsServerConnectionGnutlsPrivate
68 GTlsAuthenticationMode authentication_mode;
72 g_tls_server_connection_gnutls_init (GTlsServerConnectionGnutls *gnutls)
74 gnutls_certificate_credentials_t creds;
75 gnutls_session_t session;
77 gnutls->priv = G_TYPE_INSTANCE_GET_PRIVATE (gnutls, G_TYPE_TLS_SERVER_CONNECTION_GNUTLS, GTlsServerConnectionGnutlsPrivate);
79 creds = g_tls_connection_gnutls_get_credentials (G_TLS_CONNECTION_GNUTLS (gnutls));
80 gnutls_certificate_set_retrieve_function (creds, g_tls_server_connection_gnutls_retrieve_function);
82 session = g_tls_connection_gnutls_get_session (G_TLS_CONNECTION_GNUTLS (gnutls));
83 gnutls_db_set_retrieve_function (session, g_tls_server_connection_gnutls_db_retrieve);
84 gnutls_db_set_store_function (session, g_tls_server_connection_gnutls_db_store);
85 gnutls_db_set_remove_function (session, g_tls_server_connection_gnutls_db_remove);
89 g_tls_server_connection_gnutls_initable_init (GInitable *initable,
90 GCancellable *cancellable,
93 GTlsCertificate *cert;
95 if (!g_tls_server_connection_gnutls_parent_initable_iface->
96 init (initable, cancellable, error))
99 cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (initable));
100 if (cert && !g_tls_certificate_gnutls_has_key (G_TLS_CERTIFICATE_GNUTLS (cert)))
102 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
103 _("Certificate has no private key"));
111 g_tls_server_connection_gnutls_get_property (GObject *object,
116 GTlsServerConnectionGnutls *gnutls = G_TLS_SERVER_CONNECTION_GNUTLS (object);
120 case PROP_AUTHENTICATION_MODE:
121 g_value_set_enum (value, gnutls->priv->authentication_mode);
125 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
130 g_tls_server_connection_gnutls_set_property (GObject *object,
135 GTlsServerConnectionGnutls *gnutls = G_TLS_SERVER_CONNECTION_GNUTLS (object);
139 case PROP_AUTHENTICATION_MODE:
140 gnutls->priv->authentication_mode = g_value_get_enum (value);
144 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
149 g_tls_server_connection_gnutls_retrieve_function (gnutls_session_t session,
150 const gnutls_datum_t *req_ca_rdn,
152 const gnutls_pk_algorithm_t *pk_algos,
156 g_tls_connection_gnutls_get_certificate (gnutls_transport_get_ptr (session), st);
161 g_tls_server_connection_gnutls_failed (GTlsConnectionGnutls *conn)
163 gnutls_db_remove_session (g_tls_connection_gnutls_get_session (conn));
167 g_tls_server_connection_gnutls_begin_handshake (GTlsConnectionGnutls *conn)
169 GTlsServerConnectionGnutls *gnutls = G_TLS_SERVER_CONNECTION_GNUTLS (conn);
170 gnutls_session_t session;
171 gnutls_certificate_request_t req_mode;
173 switch (gnutls->priv->authentication_mode)
175 case G_TLS_AUTHENTICATION_REQUESTED:
176 req_mode = GNUTLS_CERT_REQUEST;
178 case G_TLS_AUTHENTICATION_REQUIRED:
179 req_mode = GNUTLS_CERT_REQUIRE;
182 req_mode = GNUTLS_CERT_IGNORE;
186 session = g_tls_connection_gnutls_get_session (conn);
187 gnutls_certificate_server_set_request (session, req_mode);
191 g_tls_server_connection_gnutls_finish_handshake (GTlsConnectionGnutls *gnutls,
192 GError **inout_error)
196 /* Session cache management */
199 g_tls_server_connection_gnutls_db_store (void *user_data,
203 GBytes *session_id, *session_data;
205 session_id = g_bytes_new (key.data, key.size);
206 session_data = g_bytes_new (data.data, data.size);
207 g_tls_backend_gnutls_store_session (GNUTLS_SERVER, session_id, session_data);
208 g_bytes_unref (session_id);
209 g_bytes_unref (session_data);
215 g_tls_server_connection_gnutls_db_remove (void *user_data,
220 session_id = g_bytes_new (key.data, key.size);
221 g_tls_backend_gnutls_remove_session (GNUTLS_SERVER, session_id);
222 g_bytes_unref (session_id);
227 static gnutls_datum_t
228 g_tls_server_connection_gnutls_db_retrieve (void *user_data,
231 GBytes *session_id, *session_data;
234 session_id = g_bytes_new (key.data, key.size);
235 session_data = g_tls_backend_gnutls_lookup_session (GNUTLS_SERVER, session_id);
236 g_bytes_unref (session_id);
240 data.size = g_bytes_get_size (session_data);
241 data.data = gnutls_malloc (data.size);
242 memcpy (data.data, g_bytes_get_data (session_data, NULL), data.size);
243 g_bytes_unref (session_data);
255 g_tls_server_connection_gnutls_class_init (GTlsServerConnectionGnutlsClass *klass)
257 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
258 GTlsConnectionGnutlsClass *connection_gnutls_class = G_TLS_CONNECTION_GNUTLS_CLASS (klass);
260 g_type_class_add_private (klass, sizeof (GTlsServerConnectionGnutlsPrivate));
262 gobject_class->get_property = g_tls_server_connection_gnutls_get_property;
263 gobject_class->set_property = g_tls_server_connection_gnutls_set_property;
265 connection_gnutls_class->failed = g_tls_server_connection_gnutls_failed;
266 connection_gnutls_class->begin_handshake = g_tls_server_connection_gnutls_begin_handshake;
267 connection_gnutls_class->finish_handshake = g_tls_server_connection_gnutls_finish_handshake;
269 g_object_class_override_property (gobject_class, PROP_AUTHENTICATION_MODE, "authentication-mode");
273 g_tls_server_connection_gnutls_server_connection_interface_init (GTlsServerConnectionInterface *iface)
278 g_tls_server_connection_gnutls_initable_interface_init (GInitableIface *iface)
280 g_tls_server_connection_gnutls_parent_initable_iface = g_type_interface_peek_parent (iface);
282 iface->init = g_tls_server_connection_gnutls_initable_init;