Mercurial > pidgin
annotate plugins/ssl/ssl-gnutls.c @ 13691:87b027bb1f15
[gaim-migrate @ 16094]
SF Patch #1462332 from cbanal
"When updating an avatar and the accounts vcard / info
is empty. The resulting vCard xml that is sent does not
contain the proper attributes.
This causes the vCard update to be ignored by the
jabber server."
I'm not 100% positive about this, but it seems right.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Tue, 25 Apr 2006 17:19:45 +0000 |
parents | 33bef17125c2 |
children | 7d513e44201b |
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 |
103 ssl_gnutls_connect_cb(gpointer data, gint source, GaimInputCondition cond) | |
104 { | |
105 GaimSslConnection *gsc = (GaimSslConnection *)data; | |
106 GaimSslGnutlsData *gnutls_data; | |
107 static const int cert_type_priority[2] = { GNUTLS_CRT_X509, 0 }; | |
108 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
109 if(source < 0) { |
8362 | 110 if(gsc->error_cb != NULL) |
111 gsc->error_cb(gsc, GAIM_SSL_CONNECT_FAILED, gsc->connect_cb_data); | |
112 | |
113 gaim_ssl_close(gsc); | |
7016 | 114 return; |
8362 | 115 } |
7016 | 116 |
117 gsc->fd = source; | |
118 | |
119 gnutls_data = g_new0(GaimSslGnutlsData, 1); | |
120 gsc->private_data = gnutls_data; | |
121 | |
122 gnutls_init(&gnutls_data->session, GNUTLS_CLIENT); | |
123 gnutls_set_default_priority(gnutls_data->session); | |
124 | |
125 gnutls_certificate_type_set_priority(gnutls_data->session, | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
126 cert_type_priority); |
7016 | 127 |
128 gnutls_credentials_set(gnutls_data->session, GNUTLS_CRD_CERTIFICATE, | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
129 xcred); |
7016 | 130 |
131 gnutls_transport_set_ptr(gnutls_data->session, GINT_TO_POINTER(source)); | |
132 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
133 gnutls_data->handshake_handler = gaim_input_add(gsc->fd, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
134 GAIM_INPUT_READ, ssl_gnutls_handshake_cb, gsc); |
7016 | 135 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
136 ssl_gnutls_handshake_cb(gsc, gsc->fd, GAIM_INPUT_READ); |
7016 | 137 } |
138 | |
139 static void | |
140 ssl_gnutls_close(GaimSslConnection *gsc) | |
141 { | |
142 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc); | |
143 | |
7467 | 144 if(!gnutls_data) |
145 return; | |
146 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
147 if(gnutls_data->handshake_handler) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
148 gaim_input_remove(gnutls_data->handshake_handler); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
149 |
7016 | 150 gnutls_bye(gnutls_data->session, GNUTLS_SHUT_RDWR); |
151 | |
152 gnutls_deinit(gnutls_data->session); | |
153 | |
154 g_free(gnutls_data); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
155 gsc->private_data = NULL; |
7016 | 156 } |
157 | |
158 static size_t | |
159 ssl_gnutls_read(GaimSslConnection *gsc, void *data, size_t len) | |
160 { | |
161 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
162 ssize_t s; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
163 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
164 s = gnutls_record_recv(gnutls_data->session, data, len); |
7016 | 165 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
166 if(s == GNUTLS_E_AGAIN || s == GNUTLS_E_INTERRUPTED) { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
167 s = -1; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
168 errno = EAGAIN; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
169 } else if(s < 0) { |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7631
diff
changeset
|
170 gaim_debug_error("gnutls", "receive failed: %d\n", s); |
7016 | 171 s = 0; |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7631
diff
changeset
|
172 } |
7016 | 173 |
174 return s; | |
175 } | |
176 | |
177 static size_t | |
178 ssl_gnutls_write(GaimSslConnection *gsc, const void *data, size_t len) | |
179 { | |
180 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
181 ssize_t s = 0; |
7016 | 182 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
183 /* XXX: when will gnutls_data be NULL? */ |
7467 | 184 if(gnutls_data) |
185 s = gnutls_record_send(gnutls_data->session, data, len); | |
7016 | 186 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
187 if(s == GNUTLS_E_AGAIN || s == GNUTLS_E_INTERRUPTED) { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
188 s = -1; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
189 errno = EAGAIN; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
190 } else if(s < 0) { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
191 gaim_debug_error("gnutls", "send failed: %d\n", s); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
192 s = 0; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
193 } |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
194 |
7016 | 195 return s; |
196 } | |
197 | |
198 static GaimSslOps ssl_ops = | |
199 { | |
200 ssl_gnutls_init, | |
201 ssl_gnutls_uninit, | |
202 ssl_gnutls_connect_cb, | |
203 ssl_gnutls_close, | |
204 ssl_gnutls_read, | |
205 ssl_gnutls_write | |
206 }; | |
207 | |
208 #endif /* HAVE_GNUTLS */ | |
209 | |
210 static gboolean | |
211 plugin_load(GaimPlugin *plugin) | |
212 { | |
213 #ifdef HAVE_GNUTLS | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
214 if(!gaim_ssl_get_ops()) { |
7862 | 215 gaim_ssl_set_ops(&ssl_ops); |
216 } | |
7016 | 217 |
11033
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
9943
diff
changeset
|
218 /* 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
|
219 ssl_gnutls_init_gnutls(); |
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
9943
diff
changeset
|
220 |
7016 | 221 return TRUE; |
222 #else | |
223 return FALSE; | |
224 #endif | |
225 } | |
226 | |
227 static gboolean | |
228 plugin_unload(GaimPlugin *plugin) | |
229 { | |
7050
e8cd8827fb25
[gaim-migrate @ 7613]
Christian Hammond <chipx86@chipx86.com>
parents:
7016
diff
changeset
|
230 #ifdef HAVE_GNUTLS |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11513
diff
changeset
|
231 if(gaim_ssl_get_ops() == &ssl_ops) { |
7862 | 232 gaim_ssl_set_ops(NULL); |
233 } | |
7050
e8cd8827fb25
[gaim-migrate @ 7613]
Christian Hammond <chipx86@chipx86.com>
parents:
7016
diff
changeset
|
234 #endif |
e8cd8827fb25
[gaim-migrate @ 7613]
Christian Hammond <chipx86@chipx86.com>
parents:
7016
diff
changeset
|
235 |
7016 | 236 return TRUE; |
237 } | |
238 | |
239 static GaimPluginInfo info = | |
240 { | |
9943 | 241 GAIM_PLUGIN_MAGIC, |
242 GAIM_MAJOR_VERSION, | |
243 GAIM_MINOR_VERSION, | |
7016 | 244 GAIM_PLUGIN_STANDARD, /**< type */ |
245 NULL, /**< ui_requirement */ | |
246 GAIM_PLUGIN_FLAG_INVISIBLE, /**< flags */ | |
247 NULL, /**< dependencies */ | |
248 GAIM_PRIORITY_DEFAULT, /**< priority */ | |
249 | |
250 SSL_GNUTLS_PLUGIN_ID, /**< id */ | |
251 N_("GNUTLS"), /**< name */ | |
252 VERSION, /**< version */ | |
253 /** summary */ | |
254 N_("Provides SSL support through GNUTLS."), | |
255 /** description */ | |
256 N_("Provides SSL support through GNUTLS."), | |
257 "Christian Hammond <chipx86@gnupdate.org>", | |
258 GAIM_WEBSITE, /**< homepage */ | |
259 | |
260 plugin_load, /**< load */ | |
261 plugin_unload, /**< unload */ | |
262 NULL, /**< destroy */ | |
263 | |
264 NULL, /**< ui_info */ | |
11513 | 265 NULL, /**< extra_info */ |
266 NULL, /**< prefs_info */ | |
267 NULL /**< actions */ | |
7016 | 268 }; |
269 | |
270 static void | |
271 init_plugin(GaimPlugin *plugin) | |
272 { | |
273 } | |
274 | |
275 GAIM_INIT_PLUGIN(ssl_gnutls, init_plugin, info) |