comparison libpurple/plugins/ssl/ssl-gnutls.c @ 15373:5fe8042783c1

Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author Sean Egan <seanegan@gmail.com>
date Sat, 20 Jan 2007 02:32:10 +0000
parents
children eed84b59c252
comparison
equal deleted inserted replaced
15372:f79e0f4df793 15373:5fe8042783c1
1 /**
2 * @file ssl-gnutls.c GNUTLS SSL plugin.
3 *
4 * gaim
5 *
6 * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22 #include "internal.h"
23 #include "debug.h"
24 #include "plugin.h"
25 #include "sslconn.h"
26 #include "version.h"
27
28 #define SSL_GNUTLS_PLUGIN_ID "ssl-gnutls"
29
30 #ifdef HAVE_GNUTLS
31
32 #include <gnutls/gnutls.h>
33
34 typedef struct
35 {
36 gnutls_session session;
37 guint handshake_handler;
38 } GaimSslGnutlsData;
39
40 #define GAIM_SSL_GNUTLS_DATA(gsc) ((GaimSslGnutlsData *)gsc->private_data)
41
42 static gnutls_certificate_client_credentials xcred;
43
44 static void
45 ssl_gnutls_init_gnutls(void)
46 {
47 gnutls_global_init();
48
49 gnutls_certificate_allocate_credentials(&xcred);
50 gnutls_certificate_set_x509_trust_file(xcred, "ca.pem",
51 GNUTLS_X509_FMT_PEM);
52 }
53
54 static gboolean
55 ssl_gnutls_init(void)
56 {
57 return TRUE;
58 }
59
60 static void
61 ssl_gnutls_uninit(void)
62 {
63 gnutls_global_deinit();
64
65 gnutls_certificate_free_credentials(xcred);
66 }
67
68
69 static void ssl_gnutls_handshake_cb(gpointer data, gint source,
70 GaimInputCondition cond)
71 {
72 GaimSslConnection *gsc = data;
73 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc);
74 ssize_t ret;
75
76 gaim_debug_info("gnutls", "Handshaking\n");
77 ret = gnutls_handshake(gnutls_data->session);
78
79 if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
80 return;
81
82 gaim_input_remove(gnutls_data->handshake_handler);
83 gnutls_data->handshake_handler = 0;
84
85 if(ret != 0) {
86 gaim_debug_error("gnutls", "Handshake failed. Error %d\n", ret);
87
88 if(gsc->error_cb != NULL)
89 gsc->error_cb(gsc, GAIM_SSL_HANDSHAKE_FAILED,
90 gsc->connect_cb_data);
91
92 gaim_ssl_close(gsc);
93 } else {
94 gaim_debug_info("gnutls", "Handshake complete\n");
95
96 gsc->connect_cb(gsc->connect_cb_data, gsc, cond);
97 }
98
99 }
100
101
102 static void
103 ssl_gnutls_connect(GaimSslConnection *gsc)
104 {
105 GaimSslGnutlsData *gnutls_data;
106 static const int cert_type_priority[2] = { GNUTLS_CRT_X509, 0 };
107
108 gnutls_data = g_new0(GaimSslGnutlsData, 1);
109 gsc->private_data = gnutls_data;
110
111 gnutls_init(&gnutls_data->session, GNUTLS_CLIENT);
112 gnutls_set_default_priority(gnutls_data->session);
113
114 gnutls_certificate_type_set_priority(gnutls_data->session,
115 cert_type_priority);
116
117 gnutls_credentials_set(gnutls_data->session, GNUTLS_CRD_CERTIFICATE,
118 xcred);
119
120 gnutls_transport_set_ptr(gnutls_data->session, GINT_TO_POINTER(gsc->fd));
121
122 gnutls_data->handshake_handler = gaim_input_add(gsc->fd,
123 GAIM_INPUT_READ, ssl_gnutls_handshake_cb, gsc);
124
125 ssl_gnutls_handshake_cb(gsc, gsc->fd, GAIM_INPUT_READ);
126 }
127
128 static void
129 ssl_gnutls_close(GaimSslConnection *gsc)
130 {
131 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc);
132
133 if(!gnutls_data)
134 return;
135
136 if(gnutls_data->handshake_handler)
137 gaim_input_remove(gnutls_data->handshake_handler);
138
139 gnutls_bye(gnutls_data->session, GNUTLS_SHUT_RDWR);
140
141 gnutls_deinit(gnutls_data->session);
142
143 g_free(gnutls_data);
144 gsc->private_data = NULL;
145 }
146
147 static size_t
148 ssl_gnutls_read(GaimSslConnection *gsc, void *data, size_t len)
149 {
150 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc);
151 ssize_t s;
152
153 s = gnutls_record_recv(gnutls_data->session, data, len);
154
155 if(s == GNUTLS_E_AGAIN || s == GNUTLS_E_INTERRUPTED) {
156 s = -1;
157 errno = EAGAIN;
158 } else if(s < 0) {
159 gaim_debug_error("gnutls", "receive failed: %d\n", s);
160 s = 0;
161 }
162
163 return s;
164 }
165
166 static size_t
167 ssl_gnutls_write(GaimSslConnection *gsc, const void *data, size_t len)
168 {
169 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc);
170 ssize_t s = 0;
171
172 /* XXX: when will gnutls_data be NULL? */
173 if(gnutls_data)
174 s = gnutls_record_send(gnutls_data->session, data, len);
175
176 if(s == GNUTLS_E_AGAIN || s == GNUTLS_E_INTERRUPTED) {
177 s = -1;
178 errno = EAGAIN;
179 } else if(s < 0) {
180 gaim_debug_error("gnutls", "send failed: %d\n", s);
181 s = 0;
182 }
183
184 return s;
185 }
186
187 static GaimSslOps ssl_ops =
188 {
189 ssl_gnutls_init,
190 ssl_gnutls_uninit,
191 ssl_gnutls_connect,
192 ssl_gnutls_close,
193 ssl_gnutls_read,
194 ssl_gnutls_write
195 };
196
197 #endif /* HAVE_GNUTLS */
198
199 static gboolean
200 plugin_load(GaimPlugin *plugin)
201 {
202 #ifdef HAVE_GNUTLS
203 if(!gaim_ssl_get_ops()) {
204 gaim_ssl_set_ops(&ssl_ops);
205 }
206
207 /* Init GNUTLS now so others can use it even if sslconn never does */
208 ssl_gnutls_init_gnutls();
209
210 return TRUE;
211 #else
212 return FALSE;
213 #endif
214 }
215
216 static gboolean
217 plugin_unload(GaimPlugin *plugin)
218 {
219 #ifdef HAVE_GNUTLS
220 if(gaim_ssl_get_ops() == &ssl_ops) {
221 gaim_ssl_set_ops(NULL);
222 }
223 #endif
224
225 return TRUE;
226 }
227
228 static GaimPluginInfo info =
229 {
230 GAIM_PLUGIN_MAGIC,
231 GAIM_MAJOR_VERSION,
232 GAIM_MINOR_VERSION,
233 GAIM_PLUGIN_STANDARD, /**< type */
234 NULL, /**< ui_requirement */
235 GAIM_PLUGIN_FLAG_INVISIBLE, /**< flags */
236 NULL, /**< dependencies */
237 GAIM_PRIORITY_DEFAULT, /**< priority */
238
239 SSL_GNUTLS_PLUGIN_ID, /**< id */
240 N_("GNUTLS"), /**< name */
241 VERSION, /**< version */
242 /** summary */
243 N_("Provides SSL support through GNUTLS."),
244 /** description */
245 N_("Provides SSL support through GNUTLS."),
246 "Christian Hammond <chipx86@gnupdate.org>",
247 GAIM_WEBSITE, /**< homepage */
248
249 plugin_load, /**< load */
250 plugin_unload, /**< unload */
251 NULL, /**< destroy */
252
253 NULL, /**< ui_info */
254 NULL, /**< extra_info */
255 NULL, /**< prefs_info */
256 NULL /**< actions */
257 };
258
259 static void
260 init_plugin(GaimPlugin *plugin)
261 {
262 }
263
264 GAIM_INIT_PLUGIN(ssl_gnutls, init_plugin, info)