2 ** Copyright (C) 2006 Thadeu Lima de Souza Cascardo <cascardo@minaslivre.org>
3 ** Copyright (C) 2009 Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
10 ** This program 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
13 ** GNU General Public License for more details.
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include <gnutls/gnutls.h>
28 #define container_of(ptr, type, member) ({ \
29 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
30 (type *)( (char *)__mptr - offsetof(type,member) );})
35 gnutls_session_t session;
40 static struct ssl_data *
41 ssl_data_new (char *server)
44 int kx_prio[] = {GNUTLS_KX_RSA, 0};
45 gnutls_certificate_credentials cred;
46 gnutls_certificate_allocate_credentials (&cred);
47 ssl = g_slice_new (struct ssl_data);
48 ssl->server = g_strdup (server);
49 gnutls_init (&ssl->session, GNUTLS_CLIENT);
50 gnutls_set_default_priority (ssl->session);
51 gnutls_set_default_priority (ssl->session);
52 gnutls_kx_set_priority (ssl->session, kx_prio);
53 gnutls_credentials_set (ssl->session, GNUTLS_CRD_CERTIFICATE, cred);
54 ssl->buffer = g_string_sized_new (4096);
55 ssl->handshaking = FALSE;
60 ssl_data_destroy (struct ssl_data *ssl)
62 gnutls_deinit (ssl->session);
64 g_string_free (ssl->buffer, TRUE);
65 g_slice_free (struct ssl_data, ssl);
69 ssl_push (gnutls_transport_ptr_t ptr, const void *buffer, size_t len)
71 net_hook_t *hook = ptr;
72 struct ssl_data *ssl = hook->data;
74 if (ssl->handshaking == TRUE)
76 g_io_channel_write_chars (hook->conn->iochannel, buffer, len,
80 gnet_conn_write (hook->conn, (void *) buffer, len);
85 ssl_pull (gnutls_transport_ptr_t ptr, void *buffer, size_t len)
87 net_hook_t *hook = ptr;
88 struct ssl_data *ssl = hook->data;
90 if (ssl->handshaking == TRUE)
92 g_io_channel_read_chars (hook->conn->iochannel, buffer, len,
96 if (len > ssl->buffer->len)
99 memcpy (buffer, ssl->buffer->str, r);
100 g_string_truncate (ssl->buffer, 0);
105 memcpy (buffer, ssl->buffer->str, r);
106 g_string_erase (ssl->buffer, 0, r);
110 gnutls_transport_set_errno (ssl->session, EAGAIN);
117 ssl_server_connect (net_hook_t *hook)
119 struct ssl_data *ssl = hook->data;
121 gnutls_transport_set_ptr (ssl->session, (gnutls_transport_ptr_t) hook);
122 gnutls_transport_set_push_function (ssl->session, ssl_push);
123 gnutls_transport_set_pull_function (ssl->session, ssl_pull);
124 ssl->handshaking = TRUE;
125 if ((error = gnutls_handshake (ssl->session)) < 0)
127 g_message ("%satal error while doing TLS handshaking.\n",
128 gnutls_error_is_fatal (error) ? "F" : "Nonf");
129 g_message ("%s\n", gnutls_strerror (error));
131 ssl->handshaking = FALSE;
135 ssl_server_close (net_hook_t *hook)
137 struct ssl_data *ssl = hook->data;
140 hook->peer->peer = NULL;
141 gnet_conn_disconnect (hook->peer->conn);
143 gnet_conn_delete (hook->conn);
146 gnutls_bye (ssl->session, GNUTLS_SHUT_RDWR);
147 ssl_data_destroy (ssl);
149 g_slice_free (net_hook_t, hook);
153 ssl_server_write (net_hook_t *hook)
158 ssl_server_read (net_hook_t *hook, gchar *buffer, size_t len)
160 struct ssl_data *ssl = hook->data;
162 g_string_append_len (ssl->buffer, buffer, len);
165 r = gnutls_record_recv (ssl->session, buffer, len);
167 gnet_conn_write (hook->peer->conn, buffer, r);
172 ssl_server_error (net_hook_t *hook)
174 g_message ("Error in POP3 client connection.");
178 ssl_server_hook_new (net_hook_t *client_hook, char *server)
181 hook = g_slice_new (net_hook_t);
182 hook->conn = gnet_conn_new (server, 995, nethook_event, hook);
183 hook->peer = client_hook;
185 hook->connect = ssl_server_connect;
186 hook->close = ssl_server_close;
187 hook->write = ssl_server_write;
188 hook->read = ssl_server_read;
189 hook->data = ssl_data_new (server);
190 gnet_conn_connect (hook->conn);
191 gnet_conn_read (hook->conn);
196 ssl_connect (net_hook_t *hook)
201 ssl_close (net_hook_t *hook)
206 ssl_write (net_hook_t *hook)
211 ssl_read (net_hook_t *hook, gchar *buffer, size_t len)
213 struct ssl_data *ssl = hook->peer->data;
214 gnutls_record_send (ssl->session, buffer, len);
218 ssl_error (net_hook_t *hook)
223 ssl_hook_new (GConn *conn, char *server)
226 hook = g_slice_new (net_hook_t);
229 hook->server = FALSE;
230 hook->connect = ssl_connect;
231 hook->close = ssl_close;
232 hook->write = ssl_write;
233 hook->read = ssl_read;
235 hook->peer = ssl_server_hook_new (hook, server);
236 gnet_conn_set_callback (hook->conn, nethook_event, hook);
241 ssl_destroy (net_hook_t *hook)
243 g_slice_free (net_hook_t, hook);