Mercurial > pidgin
annotate plugins/ssl/ssl-nss.c @ 12187:c4c612b8a648
[gaim-migrate @ 14489]
We don't want "Gaim is starting" and "Gaim is exiting" messages in
the system log, do we? If someone wants them, you should add them
in somewhere before you forget about it.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Tue, 22 Nov 2005 04:49:33 +0000 |
parents | c18bd02be106 |
children | 8f8087bc9732 |
rev | line source |
---|---|
7016 | 1 /** |
2 * @file ssl-nss.c Mozilla NSS 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 |
7029
b80c7a4dfae7
[gaim-migrate @ 7592]
Christian Hammond <chipx86@chipx86.com>
parents:
7028
diff
changeset
|
28 #define SSL_NSS_PLUGIN_ID "ssl-nss" |
7016 | 29 |
30 #ifdef HAVE_NSS | |
31 | |
9582
fec83fb0b6a9
[gaim-migrate @ 10425]
Christian Hammond <chipx86@chipx86.com>
parents:
8749
diff
changeset
|
32 #undef HAVE_LONG_LONG /* Make Mozilla less angry. If angry, Mozilla SMASH! */ |
fec83fb0b6a9
[gaim-migrate @ 10425]
Christian Hammond <chipx86@chipx86.com>
parents:
8749
diff
changeset
|
33 |
7016 | 34 #include <nspr.h> |
35 #include <private/pprio.h> | |
36 #include <nss.h> | |
37 #include <pk11func.h> | |
38 #include <prio.h> | |
39 #include <secerr.h> | |
40 #include <secmod.h> | |
41 #include <ssl.h> | |
42 #include <sslerr.h> | |
43 #include <sslproto.h> | |
44 | |
45 typedef struct | |
46 { | |
47 PRFileDesc *fd; | |
48 PRFileDesc *in; | |
49 | |
50 } GaimSslNssData; | |
51 | |
52 #define GAIM_SSL_NSS_DATA(gsc) ((GaimSslNssData *)gsc->private_data) | |
53 | |
54 static const PRIOMethods *_nss_methods = NULL; | |
55 static PRDescIdentity _identity; | |
56 | |
7993
495d3dbb4e84
[gaim-migrate @ 8670]
Christian Hammond <chipx86@chipx86.com>
parents:
7862
diff
changeset
|
57 static void |
7862 | 58 ssl_nss_init_nss(void) |
59 { | |
10519 | 60 char *lib; |
7862 | 61 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
62 NSS_NoDB_Init(NULL); | |
63 | |
64 /* TODO: Fix this so autoconf does the work trying to find this lib. */ | |
65 #ifndef _WIN32 | |
10519 | 66 lib = g_strdup(BR_LIBDIR("/libnssckbi.so")); |
7862 | 67 #else |
10519 | 68 lib = g_strdup("nssckbi.dll"); |
7862 | 69 #endif |
10519 | 70 SECMOD_AddNewModule("Builtins", lib, 0, 0); |
71 g_free(lib); | |
7862 | 72 NSS_SetDomesticPolicy(); |
73 | |
74 _identity = PR_GetUniqueIdentity("Gaim"); | |
75 _nss_methods = PR_GetDefaultIOMethods(); | |
76 } | |
77 | |
7016 | 78 static SECStatus |
79 ssl_auth_cert(void *arg, PRFileDesc *socket, PRBool checksig, | |
80 PRBool is_server) | |
81 { | |
82 return SECSuccess; | |
83 | |
84 #if 0 | |
85 CERTCertificate *cert; | |
86 void *pinArg; | |
87 SECStatus status; | |
88 | |
89 cert = SSL_PeerCertificate(socket); | |
90 pinArg = SSL_RevealPinArg(socket); | |
91 | |
92 status = CERT_VerifyCertNow((CERTCertDBHandle *)arg, cert, checksig, | |
93 certUsageSSLClient, pinArg); | |
94 | |
95 if (status != SECSuccess) { | |
96 gaim_debug_error("nss", "CERT_VerifyCertNow failed\n"); | |
97 CERT_DestroyCertificate(cert); | |
98 return status; | |
99 } | |
100 | |
101 CERT_DestroyCertificate(cert); | |
102 return SECSuccess; | |
103 #endif | |
104 } | |
105 | |
106 static SECStatus | |
107 ssl_bad_cert(void *arg, PRFileDesc *socket) | |
108 { | |
109 SECStatus status = SECFailure; | |
110 PRErrorCode err; | |
111 | |
112 if (arg == NULL) | |
113 return status; | |
114 | |
115 *(PRErrorCode *)arg = err = PORT_GetError(); | |
116 | |
117 switch (err) | |
118 { | |
119 case SEC_ERROR_INVALID_AVA: | |
120 case SEC_ERROR_INVALID_TIME: | |
121 case SEC_ERROR_BAD_SIGNATURE: | |
122 case SEC_ERROR_EXPIRED_CERTIFICATE: | |
123 case SEC_ERROR_UNKNOWN_ISSUER: | |
124 case SEC_ERROR_UNTRUSTED_CERT: | |
125 case SEC_ERROR_CERT_VALID: | |
126 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: | |
127 case SEC_ERROR_CRL_EXPIRED: | |
128 case SEC_ERROR_CRL_BAD_SIGNATURE: | |
129 case SEC_ERROR_EXTENSION_VALUE_INVALID: | |
130 case SEC_ERROR_CA_CERT_INVALID: | |
131 case SEC_ERROR_CERT_USAGES_INVALID: | |
132 case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION: | |
133 status = SECSuccess; | |
134 break; | |
135 | |
136 default: | |
137 status = SECFailure; | |
138 break; | |
139 } | |
140 | |
141 gaim_debug_error("nss", "Bad certificate: %d\n"); | |
142 | |
143 return status; | |
144 } | |
145 | |
146 static gboolean | |
147 ssl_nss_init(void) | |
148 { | |
7862 | 149 return TRUE; |
7016 | 150 } |
151 | |
152 static void | |
153 ssl_nss_uninit(void) | |
154 { | |
155 PR_Cleanup(); | |
156 | |
157 _nss_methods = NULL; | |
158 } | |
159 | |
160 static void | |
161 ssl_nss_connect_cb(gpointer data, gint source, GaimInputCondition cond) | |
162 { | |
163 GaimSslConnection *gsc = (GaimSslConnection *)data; | |
164 GaimSslNssData *nss_data = g_new0(GaimSslNssData, 1); | |
165 PRSocketOptionData socket_opt; | |
166 | |
167 gsc->private_data = nss_data; | |
168 | |
169 gsc->fd = source; | |
170 | |
171 nss_data->fd = PR_ImportTCPSocket(gsc->fd); | |
172 | |
173 if (nss_data->fd == NULL) | |
174 { | |
175 gaim_debug_error("nss", "nss_data->fd == NULL!\n"); | |
176 | |
8362 | 177 if (gsc->error_cb != NULL) |
178 gsc->error_cb(gsc, GAIM_SSL_CONNECT_FAILED, gsc->connect_cb_data); | |
179 | |
7016 | 180 gaim_ssl_close((GaimSslConnection *)gsc); |
181 | |
182 return; | |
183 } | |
184 | |
185 socket_opt.option = PR_SockOpt_Nonblocking; | |
186 socket_opt.value.non_blocking = PR_FALSE; | |
187 | |
188 PR_SetSocketOption(nss_data->fd, &socket_opt); | |
189 | |
190 nss_data->in = SSL_ImportFD(NULL, nss_data->fd); | |
191 | |
192 if (nss_data->in == NULL) | |
193 { | |
194 gaim_debug_error("nss", "nss_data->in == NUL!\n"); | |
195 | |
8362 | 196 if (gsc->error_cb != NULL) |
197 gsc->error_cb(gsc, GAIM_SSL_CONNECT_FAILED, gsc->connect_cb_data); | |
198 | |
7016 | 199 gaim_ssl_close((GaimSslConnection *)gsc); |
200 | |
201 return; | |
202 } | |
203 | |
204 SSL_OptionSet(nss_data->in, SSL_SECURITY, PR_TRUE); | |
205 SSL_OptionSet(nss_data->in, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); | |
206 | |
207 SSL_AuthCertificateHook(nss_data->in, | |
208 (SSLAuthCertificate)ssl_auth_cert, | |
209 (void *)CERT_GetDefaultCertDB()); | |
210 SSL_BadCertHook(nss_data->in, (SSLBadCertHandler)ssl_bad_cert, NULL); | |
211 | |
7157 | 212 if(gsc->host) |
213 SSL_SetURL(nss_data->in, gsc->host); | |
7016 | 214 |
215 SSL_ResetHandshake(nss_data->in, PR_FALSE); | |
216 | |
217 if (SSL_ForceHandshake(nss_data->in)) | |
218 { | |
219 gaim_debug_error("nss", "Handshake failed\n"); | |
220 | |
7274
448e39ace278
[gaim-migrate @ 7851]
Christian Hammond <chipx86@chipx86.com>
parents:
7157
diff
changeset
|
221 if (gsc->error_cb != NULL) |
8360 | 222 gsc->error_cb(gsc, GAIM_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); |
7274
448e39ace278
[gaim-migrate @ 7851]
Christian Hammond <chipx86@chipx86.com>
parents:
7157
diff
changeset
|
223 |
7016 | 224 gaim_ssl_close(gsc); |
225 | |
226 return; | |
227 } | |
228 | |
229 gsc->connect_cb(gsc->connect_cb_data, gsc, cond); | |
230 } | |
231 | |
232 static void | |
233 ssl_nss_close(GaimSslConnection *gsc) | |
234 { | |
235 GaimSslNssData *nss_data = GAIM_SSL_NSS_DATA(gsc); | |
236 | |
7467 | 237 if(!nss_data) |
238 return; | |
239 | |
7016 | 240 if (nss_data->in) PR_Close(nss_data->in); |
241 /* if (nss_data->fd) PR_Close(nss_data->fd); */ | |
242 | |
243 g_free(nss_data); | |
244 } | |
245 | |
246 static size_t | |
247 ssl_nss_read(GaimSslConnection *gsc, void *data, size_t len) | |
248 { | |
249 GaimSslNssData *nss_data = GAIM_SSL_NSS_DATA(gsc); | |
250 | |
251 return PR_Read(nss_data->in, data, len); | |
252 } | |
253 | |
254 static size_t | |
255 ssl_nss_write(GaimSslConnection *gsc, const void *data, size_t len) | |
256 { | |
257 GaimSslNssData *nss_data = GAIM_SSL_NSS_DATA(gsc); | |
258 | |
7467 | 259 if(!nss_data) |
260 return 0; | |
261 | |
7016 | 262 return PR_Write(nss_data->in, data, len); |
263 } | |
264 | |
265 static GaimSslOps ssl_ops = | |
266 { | |
267 ssl_nss_init, | |
268 ssl_nss_uninit, | |
269 ssl_nss_connect_cb, | |
270 ssl_nss_close, | |
271 ssl_nss_read, | |
272 ssl_nss_write | |
273 }; | |
274 | |
275 #endif /* HAVE_NSS */ | |
276 | |
277 | |
278 static gboolean | |
279 plugin_load(GaimPlugin *plugin) | |
280 { | |
281 #ifdef HAVE_NSS | |
7862 | 282 if (!gaim_ssl_get_ops()) { |
283 gaim_ssl_set_ops(&ssl_ops); | |
284 } | |
7016 | 285 |
11033
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
286 /* Init NSS now, so others can use it even if sslconn never does */ |
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
287 ssl_nss_init_nss(); |
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10519
diff
changeset
|
288 |
7016 | 289 return TRUE; |
290 #else | |
291 return FALSE; | |
292 #endif | |
293 } | |
294 | |
295 static gboolean | |
296 plugin_unload(GaimPlugin *plugin) | |
297 { | |
7053 | 298 #ifdef HAVE_NSS |
7862 | 299 if (gaim_ssl_get_ops() == &ssl_ops) { |
300 gaim_ssl_set_ops(NULL); | |
301 } | |
7050
e8cd8827fb25
[gaim-migrate @ 7613]
Christian Hammond <chipx86@chipx86.com>
parents:
7029
diff
changeset
|
302 #endif |
e8cd8827fb25
[gaim-migrate @ 7613]
Christian Hammond <chipx86@chipx86.com>
parents:
7029
diff
changeset
|
303 |
7016 | 304 return TRUE; |
305 } | |
306 | |
307 static GaimPluginInfo info = | |
308 { | |
9943 | 309 GAIM_PLUGIN_MAGIC, |
310 GAIM_MAJOR_VERSION, | |
311 GAIM_MINOR_VERSION, | |
7016 | 312 GAIM_PLUGIN_STANDARD, /**< type */ |
313 NULL, /**< ui_requirement */ | |
314 GAIM_PLUGIN_FLAG_INVISIBLE, /**< flags */ | |
315 NULL, /**< dependencies */ | |
316 GAIM_PRIORITY_DEFAULT, /**< priority */ | |
317 | |
7029
b80c7a4dfae7
[gaim-migrate @ 7592]
Christian Hammond <chipx86@chipx86.com>
parents:
7028
diff
changeset
|
318 SSL_NSS_PLUGIN_ID, /**< id */ |
7016 | 319 N_("NSS"), /**< name */ |
320 VERSION, /**< version */ | |
321 /** summary */ | |
322 N_("Provides SSL support through Mozilla NSS."), | |
323 /** description */ | |
324 N_("Provides SSL support through Mozilla NSS."), | |
325 "Christian Hammond <chipx86@gnupdate.org>", | |
326 GAIM_WEBSITE, /**< homepage */ | |
327 | |
328 plugin_load, /**< load */ | |
329 plugin_unload, /**< unload */ | |
330 NULL, /**< destroy */ | |
331 | |
332 NULL, /**< ui_info */ | |
11513 | 333 NULL, /**< extra_info */ |
334 NULL, /**< prefs_info */ | |
335 NULL /**< actions */ | |
7016 | 336 }; |
337 | |
338 static void | |
339 init_plugin(GaimPlugin *plugin) | |
340 { | |
341 } | |
342 | |
343 GAIM_INIT_PLUGIN(ssl_nss, init_plugin, info) |