Mercurial > pidgin.yaz
annotate plugins/ssl/ssl-gnutls.c @ 14161:694aae55ab6d
[gaim-migrate @ 16809]
gaim_ssl_connect's are now cancelable (without crashing, anyway)
This was relatively easy, because the PRPLs already keep a reference
to the GaimSslConnection. I just needed to update the core ssl code
to keep track of the GaimProxyConnectInfo, and to call
gaim_proxy_connect_cancel() when gaim_ssl_close() is called
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 17 Aug 2006 05:47:58 +0000 |
parents | 7d513e44201b |
children |
rev | line source |
---|---|
7016 | 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" | |
7051
e885d4963a68
[gaim-migrate @ 7614]
Christian Hammond <chipx86@chipx86.com>
parents:
7050
diff
changeset
|
23 #include "debug.h" |
7016 | 24 #include "plugin.h" |
7051
e885d4963a68
[gaim-migrate @ 7614]
Christian Hammond <chipx86@chipx86.com>
parents:
7050
diff
changeset
|
25 #include "sslconn.h" |
9943 | 26 #include "version.h" |
7016 | 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; | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
37 guint handshake_handler; |
7016 | 38 } GaimSslGnutlsData; |
39 | |
40 #define GAIM_SSL_GNUTLS_DATA(gsc) ((GaimSslGnutlsData *)gsc->private_data) | |
41 | |
42 static gnutls_certificate_client_credentials xcred; | |
43 | |
7862 | 44 static void |
45 ssl_gnutls_init_gnutls(void) | |
7016 | 46 { |
47 gnutls_global_init(); | |
48 | |
49 gnutls_certificate_allocate_credentials(&xcred); | |
50 gnutls_certificate_set_x509_trust_file(xcred, "ca.pem", | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
51 GNUTLS_X509_FMT_PEM); |
7862 | 52 } |
7016 | 53 |
7862 | 54 static gboolean |
55 ssl_gnutls_init(void) | |
56 { | |
57 return TRUE; | |
7016 | 58 } |
59 | |
60 static void | |
61 ssl_gnutls_uninit(void) | |
62 { | |
63 gnutls_global_deinit(); | |
64 | |
65 gnutls_certificate_free_credentials(xcred); | |
66 } | |
67 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
68 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
69 static void ssl_gnutls_handshake_cb(gpointer data, gint source, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
70 GaimInputCondition cond) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
71 { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
72 GaimSslConnection *gsc = data; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
73 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
74 ssize_t ret; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
75 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
76 gaim_debug_info("gnutls", "Handshaking\n"); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
77 ret = gnutls_handshake(gnutls_data->session); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
78 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
79 if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
80 return; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
81 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
82 gaim_input_remove(gnutls_data->handshake_handler); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
83 gnutls_data->handshake_handler = 0; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
84 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
85 if(ret != 0) { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
86 gaim_debug_error("gnutls", "Handshake failed. Error %d\n", ret); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
87 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
88 if(gsc->error_cb != NULL) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
89 gsc->error_cb(gsc, GAIM_SSL_HANDSHAKE_FAILED, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
90 gsc->connect_cb_data); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
91 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
92 gaim_ssl_close(gsc); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
93 } else { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
94 gaim_debug_info("gnutls", "Handshake complete\n"); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
95 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
96 gsc->connect_cb(gsc->connect_cb_data, gsc, cond); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
97 } |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
98 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
99 } |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
100 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
101 |
7016 | 102 static void |
14161 | 103 ssl_gnutls_connect(GaimSslConnection *gsc) |
7016 | 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, | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
115 cert_type_priority); |
7016 | 116 |
117 gnutls_credentials_set(gnutls_data->session, GNUTLS_CRD_CERTIFICATE, | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
118 xcred); |
7016 | 119 |
14161 | 120 gnutls_transport_set_ptr(gnutls_data->session, GINT_TO_POINTER(gsc->fd)); |
7016 | 121 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
122 gnutls_data->handshake_handler = gaim_input_add(gsc->fd, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
123 GAIM_INPUT_READ, ssl_gnutls_handshake_cb, gsc); |
7016 | 124 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
125 ssl_gnutls_handshake_cb(gsc, gsc->fd, GAIM_INPUT_READ); |
7016 | 126 } |
127 | |
128 static void | |
129 ssl_gnutls_close(GaimSslConnection *gsc) | |
130 { | |
131 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc); | |
132 | |
7467 | 133 if(!gnutls_data) |
134 return; | |
135 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
136 if(gnutls_data->handshake_handler) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
137 gaim_input_remove(gnutls_data->handshake_handler); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
138 |
7016 | 139 gnutls_bye(gnutls_data->session, GNUTLS_SHUT_RDWR); |
140 | |
141 gnutls_deinit(gnutls_data->session); | |
142 | |
143 g_free(gnutls_data); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
144 gsc->private_data = NULL; |
7016 | 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); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
151 ssize_t s; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
152 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
153 s = gnutls_record_recv(gnutls_data->session, data, len); |
7016 | 154 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
155 if(s == GNUTLS_E_AGAIN || s == GNUTLS_E_INTERRUPTED) { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
156 s = -1; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
157 errno = EAGAIN; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
158 } else if(s < 0) { |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7631
diff
changeset
|
159 gaim_debug_error("gnutls", "receive failed: %d\n", s); |
7016 | 160 s = 0; |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7631
diff
changeset
|
161 } |
7016 | 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); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
170 ssize_t s = 0; |
7016 | 171 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
172 /* XXX: when will gnutls_data be NULL? */ |
7467 | 173 if(gnutls_data) |
174 s = gnutls_record_send(gnutls_data->session, data, len); | |
7016 | 175 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
176 if(s == GNUTLS_E_AGAIN || s == GNUTLS_E_INTERRUPTED) { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
177 s = -1; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
178 errno = EAGAIN; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
179 } else if(s < 0) { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
180 gaim_debug_error("gnutls", "send failed: %d\n", s); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
181 s = 0; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
182 } |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
183 |
7016 | 184 return s; |
185 } | |
186 | |
187 static GaimSslOps ssl_ops = | |
188 { | |
189 ssl_gnutls_init, | |
190 ssl_gnutls_uninit, | |
14161 | 191 ssl_gnutls_connect, |
7016 | 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 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
203 if(!gaim_ssl_get_ops()) { |
7862 | 204 gaim_ssl_set_ops(&ssl_ops); |
205 } | |
7016 | 206 |
11033
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
9943
diff
changeset
|
207 /* Init GNUTLS now so others can use it even if sslconn never does */ |
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
9943
diff
changeset
|
208 ssl_gnutls_init_gnutls(); |
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
9943
diff
changeset
|
209 |
7016 | 210 return TRUE; |
211 #else | |
212 return FALSE; | |
213 #endif | |
214 } | |
215 | |
216 static gboolean | |
217 plugin_unload(GaimPlugin *plugin) | |
218 { | |
7050
e8cd8827fb25
[gaim-migrate @ 7613]
Christian Hammond <chipx86@chipx86.com>
parents:
7016
diff
changeset
|
219 #ifdef HAVE_GNUTLS |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
220 if(gaim_ssl_get_ops() == &ssl_ops) { |
7862 | 221 gaim_ssl_set_ops(NULL); |
222 } | |
7050
e8cd8827fb25
[gaim-migrate @ 7613]
Christian Hammond <chipx86@chipx86.com>
parents:
7016
diff
changeset
|
223 #endif |
e8cd8827fb25
[gaim-migrate @ 7613]
Christian Hammond <chipx86@chipx86.com>
parents:
7016
diff
changeset
|
224 |
7016 | 225 return TRUE; |
226 } | |
227 | |
228 static GaimPluginInfo info = | |
229 { | |
9943 | 230 GAIM_PLUGIN_MAGIC, |
231 GAIM_MAJOR_VERSION, | |
232 GAIM_MINOR_VERSION, | |
7016 | 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 */ | |
11513 | 254 NULL, /**< extra_info */ |
255 NULL, /**< prefs_info */ | |
256 NULL /**< actions */ | |
7016 | 257 }; |
258 | |
259 static void | |
260 init_plugin(GaimPlugin *plugin) | |
261 { | |
262 } | |
263 | |
264 GAIM_INIT_PLUGIN(ssl_gnutls, init_plugin, info) |