plugins/ssl/ssl-gnutls.c

branch
gaim
changeset 20470
77693555855f
parent 13071
b98e72d4089a
parent 20469
b2836a24d81e
child 20471
1966704b3e42
equal deleted inserted replaced
13071:b98e72d4089a 20470:77693555855f
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
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 static void
69 ssl_gnutls_connect_cb(gpointer data, gint source, GaimInputCondition cond)
70 {
71 GaimSslConnection *gsc = (GaimSslConnection *)data;
72 GaimSslGnutlsData *gnutls_data;
73 static const int cert_type_priority[2] = { GNUTLS_CRT_X509, 0 };
74 int ret;
75
76 if (source < 0) {
77 if(gsc->error_cb != NULL)
78 gsc->error_cb(gsc, GAIM_SSL_CONNECT_FAILED, gsc->connect_cb_data);
79
80 gaim_ssl_close(gsc);
81 return;
82 }
83
84 gsc->fd = source;
85
86 gnutls_data = g_new0(GaimSslGnutlsData, 1);
87 gsc->private_data = gnutls_data;
88
89 gnutls_init(&gnutls_data->session, GNUTLS_CLIENT);
90 gnutls_set_default_priority(gnutls_data->session);
91
92 gnutls_certificate_type_set_priority(gnutls_data->session,
93 cert_type_priority);
94
95 gnutls_credentials_set(gnutls_data->session, GNUTLS_CRD_CERTIFICATE,
96 xcred);
97
98 gnutls_transport_set_ptr(gnutls_data->session, GINT_TO_POINTER(source));
99
100
101 do
102 {
103 gaim_debug_info("gnutls", "Handshaking\n");
104 ret = gnutls_handshake(gnutls_data->session);
105 }
106 while ((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED));
107
108 if (ret < 0)
109 {
110 gaim_debug_error("gnutls", "Handshake failed. Error %d\n", ret);
111
112 if (gsc->error_cb != NULL)
113 gsc->error_cb(gsc, GAIM_SSL_HANDSHAKE_FAILED,
114 gsc->connect_cb_data);
115
116 gaim_ssl_close(gsc);
117 }
118 else
119 {
120 gaim_debug_info("gnutls", "Handshake complete\n");
121
122 gsc->connect_cb(gsc->connect_cb_data, gsc, cond);
123 }
124 }
125
126 static void
127 ssl_gnutls_close(GaimSslConnection *gsc)
128 {
129 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc);
130
131 if(!gnutls_data)
132 return;
133
134 gnutls_bye(gnutls_data->session, GNUTLS_SHUT_RDWR);
135
136 gnutls_deinit(gnutls_data->session);
137
138 g_free(gnutls_data);
139 }
140
141 static size_t
142 ssl_gnutls_read(GaimSslConnection *gsc, void *data, size_t len)
143 {
144 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc);
145 int s;
146
147 do
148 {
149 s = gnutls_record_recv(gnutls_data->session, data, len);
150 }
151 while ((s == GNUTLS_E_AGAIN) || (s == GNUTLS_E_INTERRUPTED));
152
153 if (s < 0)
154 {
155 gaim_debug_error("gnutls", "receive failed: %d\n", s);
156 s = 0;
157 }
158
159 return s;
160 }
161
162 static size_t
163 ssl_gnutls_write(GaimSslConnection *gsc, const void *data, size_t len)
164 {
165 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc);
166 size_t s = 0;
167
168 if(gnutls_data)
169 s = gnutls_record_send(gnutls_data->session, data, len);
170
171 return s;
172 }
173
174 static GaimSslOps ssl_ops =
175 {
176 ssl_gnutls_init,
177 ssl_gnutls_uninit,
178 ssl_gnutls_connect_cb,
179 ssl_gnutls_close,
180 ssl_gnutls_read,
181 ssl_gnutls_write
182 };
183
184 #endif /* HAVE_GNUTLS */
185
186 static gboolean
187 plugin_load(GaimPlugin *plugin)
188 {
189 #ifdef HAVE_GNUTLS
190 if (!gaim_ssl_get_ops()) {
191 gaim_ssl_set_ops(&ssl_ops);
192 }
193
194 /* Init GNUTLS now so others can use it even if sslconn never does */
195 ssl_gnutls_init_gnutls();
196
197 return TRUE;
198 #else
199 return FALSE;
200 #endif
201 }
202
203 static gboolean
204 plugin_unload(GaimPlugin *plugin)
205 {
206 #ifdef HAVE_GNUTLS
207 if (gaim_ssl_get_ops() == &ssl_ops) {
208 gaim_ssl_set_ops(NULL);
209 }
210 #endif
211
212 return TRUE;
213 }
214
215 static GaimPluginInfo info =
216 {
217 GAIM_PLUGIN_MAGIC,
218 GAIM_MAJOR_VERSION,
219 GAIM_MINOR_VERSION,
220 GAIM_PLUGIN_STANDARD, /**< type */
221 NULL, /**< ui_requirement */
222 GAIM_PLUGIN_FLAG_INVISIBLE, /**< flags */
223 NULL, /**< dependencies */
224 GAIM_PRIORITY_DEFAULT, /**< priority */
225
226 SSL_GNUTLS_PLUGIN_ID, /**< id */
227 N_("GNUTLS"), /**< name */
228 VERSION, /**< version */
229 /** summary */
230 N_("Provides SSL support through GNUTLS."),
231 /** description */
232 N_("Provides SSL support through GNUTLS."),
233 "Christian Hammond <chipx86@gnupdate.org>",
234 GAIM_WEBSITE, /**< homepage */
235
236 plugin_load, /**< load */
237 plugin_unload, /**< unload */
238 NULL, /**< destroy */
239
240 NULL, /**< ui_info */
241 NULL, /**< extra_info */
242 NULL, /**< prefs_info */
243 NULL /**< actions */
244 };
245
246 static void
247 init_plugin(GaimPlugin *plugin)
248 {
249 }
250
251 GAIM_INIT_PLUGIN(ssl_gnutls, init_plugin, info)

mercurial