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"
|
|
23 #include "plugin.h"
|
|
24
|
|
25 #define SSL_GNUTLS_PLUGIN_ID "ssl-gnutls"
|
|
26
|
|
27 #ifdef HAVE_GNUTLS
|
|
28
|
|
29 #include "debug.h"
|
|
30 #include "sslconn.h"
|
|
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 gboolean
|
|
45 ssl_gnutls_init(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 return TRUE;
|
|
54 }
|
|
55
|
|
56 static void
|
|
57 ssl_gnutls_uninit(void)
|
|
58 {
|
|
59 gnutls_global_deinit();
|
|
60
|
|
61 gnutls_certificate_free_credentials(xcred);
|
|
62 }
|
|
63
|
|
64 static void
|
|
65 ssl_gnutls_connect_cb(gpointer data, gint source, GaimInputCondition cond)
|
|
66 {
|
|
67 GaimSslConnection *gsc = (GaimSslConnection *)data;
|
|
68 GaimSslGnutlsData *gnutls_data;
|
|
69 static const int cert_type_priority[2] = { GNUTLS_CRT_X509, 0 };
|
|
70 int ret;
|
|
71
|
|
72 if (source < 0)
|
|
73 return;
|
|
74
|
|
75 gsc->fd = source;
|
|
76
|
|
77 gnutls_data = g_new0(GaimSslGnutlsData, 1);
|
|
78 gsc->private_data = gnutls_data;
|
|
79
|
|
80 gnutls_init(&gnutls_data->session, GNUTLS_CLIENT);
|
|
81 gnutls_set_default_priority(gnutls_data->session);
|
|
82
|
|
83 gnutls_certificate_type_set_priority(gnutls_data->session,
|
|
84 cert_type_priority);
|
|
85
|
|
86 gnutls_credentials_set(gnutls_data->session, GNUTLS_CRD_CERTIFICATE,
|
|
87 xcred);
|
|
88
|
|
89 gnutls_transport_set_ptr(gnutls_data->session, GINT_TO_POINTER(source));
|
|
90
|
|
91 gaim_debug_info("gnutls", "Handshaking\n");
|
|
92 ret = gnutls_handshake(gnutls_data->session);
|
|
93
|
|
94 if (ret < 0)
|
|
95 {
|
|
96 gaim_debug_error("gnutls", "Handshake failed\n");
|
|
97
|
|
98 /* XXX: notify the guy expecting the callback somehow? */
|
|
99 gaim_ssl_close(gsc);
|
|
100 }
|
|
101 else
|
|
102 {
|
|
103 gsc->connect_cb(gsc->connect_cb_data, gsc, cond);
|
|
104 }
|
|
105 }
|
|
106
|
|
107 static void
|
|
108 ssl_gnutls_close(GaimSslConnection *gsc)
|
|
109 {
|
|
110 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc);
|
|
111
|
|
112 gnutls_bye(gnutls_data->session, GNUTLS_SHUT_RDWR);
|
|
113
|
|
114 gnutls_deinit(gnutls_data->session);
|
|
115
|
|
116 g_free(gnutls_data);
|
|
117 }
|
|
118
|
|
119 static size_t
|
|
120 ssl_gnutls_read(GaimSslConnection *gsc, void *data, size_t len)
|
|
121 {
|
|
122 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc);
|
|
123 int s;
|
|
124
|
|
125 s = gnutls_record_recv(gnutls_data->session, data, len);
|
|
126
|
|
127 if (s < 0)
|
|
128 s = 0;
|
|
129
|
|
130 return s;
|
|
131 }
|
|
132
|
|
133 static size_t
|
|
134 ssl_gnutls_write(GaimSslConnection *gsc, const void *data, size_t len)
|
|
135 {
|
|
136 GaimSslGnutlsData *gnutls_data = GAIM_SSL_GNUTLS_DATA(gsc);
|
|
137 size_t s;
|
|
138
|
|
139 s = gnutls_record_send(gnutls_data->session, data, len);
|
|
140
|
|
141 if (s < 0)
|
|
142 s = 0;
|
|
143
|
|
144 return s;
|
|
145 }
|
|
146
|
|
147 static GaimSslOps ssl_ops =
|
|
148 {
|
|
149 ssl_gnutls_init,
|
|
150 ssl_gnutls_uninit,
|
|
151 ssl_gnutls_connect_cb,
|
|
152 ssl_gnutls_close,
|
|
153 ssl_gnutls_read,
|
|
154 ssl_gnutls_write
|
|
155 };
|
|
156
|
|
157 #endif /* HAVE_GNUTLS */
|
|
158
|
|
159 static gboolean
|
|
160 plugin_load(GaimPlugin *plugin)
|
|
161 {
|
|
162 #ifdef HAVE_GNUTLS
|
|
163 gaim_ssl_set_ops(&ssl_ops);
|
|
164
|
|
165 return TRUE;
|
|
166 #else
|
|
167 return FALSE;
|
|
168 #endif
|
|
169 }
|
|
170
|
|
171 static gboolean
|
|
172 plugin_unload(GaimPlugin *plugin)
|
|
173 {
|
|
174 return TRUE;
|
|
175 }
|
|
176
|
|
177 static GaimPluginInfo info =
|
|
178 {
|
|
179 2, /**< api_version */
|
|
180 GAIM_PLUGIN_STANDARD, /**< type */
|
|
181 NULL, /**< ui_requirement */
|
|
182 GAIM_PLUGIN_FLAG_INVISIBLE, /**< flags */
|
|
183 NULL, /**< dependencies */
|
|
184 GAIM_PRIORITY_DEFAULT, /**< priority */
|
|
185
|
|
186 SSL_GNUTLS_PLUGIN_ID, /**< id */
|
|
187 N_("GNUTLS"), /**< name */
|
|
188 VERSION, /**< version */
|
|
189 /** summary */
|
|
190 N_("Provides SSL support through GNUTLS."),
|
|
191 /** description */
|
|
192 N_("Provides SSL support through GNUTLS."),
|
|
193 "Christian Hammond <chipx86@gnupdate.org>",
|
|
194 GAIM_WEBSITE, /**< homepage */
|
|
195
|
|
196 plugin_load, /**< load */
|
|
197 plugin_unload, /**< unload */
|
|
198 NULL, /**< destroy */
|
|
199
|
|
200 NULL, /**< ui_info */
|
|
201 NULL /**< extra_info */
|
|
202 };
|
|
203
|
|
204 static void
|
|
205 init_plugin(GaimPlugin *plugin)
|
|
206 {
|
|
207 }
|
|
208
|
|
209 GAIM_INIT_PLUGIN(ssl_gnutls, init_plugin, info)
|