1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 * GIO - GLib Input, Output and Streaming Library
5 * Copyright 2010 Red Hat, Inc
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see
19 * <http://www.gnu.org/licenses/>.
21 * In addition, when the library is used with OpenSSL, a special
22 * exception applies. Refer to the LICENSE_EXCEPTION file for details.
29 #include <gnutls/gnutls.h>
30 #include <gnutls/x509.h>
32 #include "gtlsserverconnection-gnutls.h"
33 #include "gtlsbackend-gnutls.h"
34 #include "gtlscertificate-gnutls.h"
35 #include <glib/gi18n-lib.h>
40 PROP_AUTHENTICATION_MODE
43 struct _GTlsServerConnectionGnutls
45 GTlsConnectionGnutls parent_instance;
47 GTlsAuthenticationMode authentication_mode;
49 gnutls_pcert_st *pcert;
50 unsigned int pcert_length;
51 gnutls_privkey_t pkey;
54 static void g_tls_server_connection_gnutls_initable_interface_init (GInitableIface *iface);
56 static void g_tls_server_connection_gnutls_server_connection_interface_init (GTlsServerConnectionInterface *iface);
58 static int g_tls_server_connection_gnutls_handshake_thread_retrieve_function (gnutls_session_t session,
59 const gnutls_datum_t *req_ca_rdn,
61 const gnutls_pk_algorithm_t *pk_algos,
63 gnutls_pcert_st **pcert,
64 unsigned int *pcert_length,
65 gnutls_privkey_t *pkey);
67 static GInitableIface *g_tls_server_connection_gnutls_parent_initable_iface;
69 G_DEFINE_TYPE_WITH_CODE (GTlsServerConnectionGnutls, g_tls_server_connection_gnutls, G_TYPE_TLS_CONNECTION_GNUTLS,
70 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
71 g_tls_server_connection_gnutls_initable_interface_init)
72 G_IMPLEMENT_INTERFACE (G_TYPE_TLS_SERVER_CONNECTION,
73 g_tls_server_connection_gnutls_server_connection_interface_init)
74 G_IMPLEMENT_INTERFACE (G_TYPE_DTLS_SERVER_CONNECTION,
79 clear_gnutls_certificate_copy (GTlsServerConnectionGnutls *gnutls)
81 g_tls_certificate_gnutls_copy_free (gnutls->pcert, gnutls->pcert_length, gnutls->pkey);
84 gnutls->pcert_length = 0;
89 g_tls_server_connection_gnutls_init (GTlsServerConnectionGnutls *gnutls)
94 g_tls_server_connection_gnutls_finalize (GObject *object)
96 GTlsServerConnectionGnutls *gnutls = G_TLS_SERVER_CONNECTION_GNUTLS (object);
98 clear_gnutls_certificate_copy (gnutls);
100 G_OBJECT_CLASS (g_tls_server_connection_gnutls_parent_class)->finalize (object);
104 g_tls_server_connection_gnutls_initable_init (GInitable *initable,
105 GCancellable *cancellable,
108 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (initable);
109 GTlsCertificate *cert;
110 gnutls_certificate_credentials_t creds;
112 if (!g_tls_server_connection_gnutls_parent_initable_iface->init (initable, cancellable, error))
115 creds = g_tls_connection_gnutls_get_credentials (G_TLS_CONNECTION_GNUTLS (gnutls));
116 gnutls_certificate_set_retrieve_function2 (creds, g_tls_server_connection_gnutls_handshake_thread_retrieve_function);
118 /* Currently we don't know ahead of time if a PKCS #11 backed certificate has a private key. */
119 cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (initable));
120 if (cert && !g_tls_certificate_gnutls_has_key (G_TLS_CERTIFICATE_GNUTLS (cert)) &&
121 !g_tls_certificate_gnutls_is_pkcs11_backed (G_TLS_CERTIFICATE_GNUTLS (cert)))
123 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
124 _("Certificate has no private key"));
132 g_tls_server_connection_gnutls_get_property (GObject *object,
137 GTlsServerConnectionGnutls *gnutls = G_TLS_SERVER_CONNECTION_GNUTLS (object);
141 case PROP_AUTHENTICATION_MODE:
142 g_value_set_enum (value, gnutls->authentication_mode);
146 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
151 g_tls_server_connection_gnutls_set_property (GObject *object,
156 GTlsServerConnectionGnutls *gnutls = G_TLS_SERVER_CONNECTION_GNUTLS (object);
160 case PROP_AUTHENTICATION_MODE:
161 gnutls->authentication_mode = g_value_get_enum (value);
165 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
170 g_tls_server_connection_gnutls_handshake_thread_retrieve_function (gnutls_session_t session,
171 const gnutls_datum_t *req_ca_rdn,
173 const gnutls_pk_algorithm_t *pk_algos,
175 gnutls_pcert_st **pcert,
176 unsigned int *pcert_length,
177 gnutls_privkey_t *pkey)
179 GTlsServerConnectionGnutls *gnutls = G_TLS_SERVER_CONNECTION_GNUTLS (gnutls_transport_get_ptr (session));
181 clear_gnutls_certificate_copy (gnutls);
183 g_tls_connection_gnutls_handshake_thread_get_certificate (G_TLS_CONNECTION_GNUTLS (gnutls),
184 pcert, pcert_length, pkey);
186 gnutls->pcert = *pcert;
187 gnutls->pcert_length = *pcert_length;
188 gnutls->pkey = *pkey;
194 g_tls_server_connection_gnutls_prepare_handshake (GTlsConnectionBase *tls,
195 gchar **advertised_protocols)
197 GTlsServerConnectionGnutls *gnutls = G_TLS_SERVER_CONNECTION_GNUTLS (tls);
198 gnutls_session_t session;
199 gnutls_certificate_request_t req_mode;
201 switch (gnutls->authentication_mode)
203 case G_TLS_AUTHENTICATION_REQUESTED:
204 req_mode = GNUTLS_CERT_REQUEST;
206 case G_TLS_AUTHENTICATION_REQUIRED:
207 req_mode = GNUTLS_CERT_REQUIRE;
209 case G_TLS_AUTHENTICATION_NONE:
211 req_mode = GNUTLS_CERT_IGNORE;
215 session = g_tls_connection_gnutls_get_session (G_TLS_CONNECTION_GNUTLS (tls));
216 gnutls_certificate_server_set_request (session, req_mode);
218 G_TLS_CONNECTION_BASE_CLASS (g_tls_server_connection_gnutls_parent_class)->prepare_handshake (tls, advertised_protocols);
222 g_tls_server_connection_gnutls_update_credentials (GTlsConnectionGnutls *gnutls,
223 gnutls_certificate_credentials_t credentials)
225 gnutls_certificate_set_retrieve_function2 (credentials, g_tls_server_connection_gnutls_handshake_thread_retrieve_function);
229 g_tls_server_connection_gnutls_class_init (GTlsServerConnectionGnutlsClass *klass)
231 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
232 GTlsConnectionBaseClass *base_class = G_TLS_CONNECTION_BASE_CLASS (klass);
233 GTlsConnectionGnutlsClass *gnutls_class = G_TLS_CONNECTION_GNUTLS_CLASS (klass);
235 gobject_class->finalize = g_tls_server_connection_gnutls_finalize;
236 gobject_class->get_property = g_tls_server_connection_gnutls_get_property;
237 gobject_class->set_property = g_tls_server_connection_gnutls_set_property;
239 base_class->prepare_handshake = g_tls_server_connection_gnutls_prepare_handshake;
241 gnutls_class->update_credentials = g_tls_server_connection_gnutls_update_credentials;
243 g_object_class_override_property (gobject_class, PROP_AUTHENTICATION_MODE, "authentication-mode");
247 g_tls_server_connection_gnutls_server_connection_interface_init (GTlsServerConnectionInterface *iface)
252 g_tls_server_connection_gnutls_initable_interface_init (GInitableIface *iface)
254 g_tls_server_connection_gnutls_parent_initable_iface = g_type_interface_peek_parent (iface);
256 iface->init = g_tls_server_connection_gnutls_initable_init;