2 * @file sslconn.c SSL API
8 * Purple is the legal property of its developers, whose names are too numerous
9 * to list here. Please refer to the COPYRIGHT file distributed with this
10 * source distribution.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 #define _PURPLE_SSLCONN_C_
30 #include "certificate.h"
35 static gboolean _ssl_initialized
= FALSE
;
36 static PurpleSslOps
*_ssl_ops
= NULL
;
47 plugin
= purple_plugins_find_with_id("core-ssl");
49 if (plugin
!= NULL
&& !purple_plugin_is_loaded(plugin
))
50 purple_plugin_load(plugin
);
52 ops
= purple_ssl_get_ops();
53 if ((ops
== NULL
) || (ops
->init
== NULL
) || (ops
->uninit
== NULL
) ||
54 (ops
->connectfunc
== NULL
) || (ops
->close
== NULL
) ||
55 (ops
->read
== NULL
) || (ops
->write
== NULL
))
60 return (_ssl_initialized
= ops
->init());
64 purple_ssl_is_supported(void)
68 return (purple_ssl_get_ops() != NULL
);
75 purple_ssl_connect_cb(gpointer data
, gint source
, const gchar
*error_message
)
77 PurpleSslConnection
*gsc
;
81 gsc
->connect_data
= NULL
;
85 if (gsc
->error_cb
!= NULL
)
86 gsc
->error_cb(gsc
, PURPLE_SSL_CONNECT_FAILED
, gsc
->connect_cb_data
);
88 purple_ssl_close(gsc
);
94 ops
= purple_ssl_get_ops();
95 ops
->connectfunc(gsc
);
99 purple_ssl_connect(PurpleAccount
*account
, const char *host
, int port
,
100 PurpleSslInputFunction func
, PurpleSslErrorFunction error_func
,
103 return purple_ssl_connect_with_ssl_cn(account
, host
, port
, func
, error_func
,
107 PurpleSslConnection
*
108 purple_ssl_connect_with_ssl_cn(PurpleAccount
*account
, const char *host
, int port
,
109 PurpleSslInputFunction func
, PurpleSslErrorFunction error_func
,
110 const char *ssl_cn
, void *data
)
112 PurpleSslConnection
*gsc
;
114 g_return_val_if_fail(host
!= NULL
, NULL
);
115 g_return_val_if_fail(port
!= 0 && port
!= -1, NULL
);
116 g_return_val_if_fail(func
!= NULL
, NULL
);
117 g_return_val_if_fail(purple_ssl_is_supported(), NULL
);
119 if (!_ssl_initialized
)
125 gsc
= g_new0(PurpleSslConnection
, 1);
128 gsc
->host
= ssl_cn
? g_strdup(ssl_cn
) : g_strdup(host
);
130 gsc
->connect_cb_data
= data
;
131 gsc
->connect_cb
= func
;
132 gsc
->error_cb
= error_func
;
134 /* TODO: Move this elsewhere */
135 gsc
->verifier
= purple_certificate_find_verifier("x509","tls_cached");
137 gsc
->connect_data
= purple_proxy_connect(NULL
, account
, host
, port
, purple_ssl_connect_cb
, gsc
);
139 if (gsc
->connect_data
== NULL
)
147 return (PurpleSslConnection
*)gsc
;
151 recv_cb(gpointer data
, gint source
, PurpleInputCondition cond
)
153 PurpleSslConnection
*gsc
= data
;
155 gsc
->recv_cb(gsc
->recv_cb_data
, gsc
, cond
);
159 purple_ssl_input_add(PurpleSslConnection
*gsc
, PurpleSslInputFunction func
,
162 g_return_if_fail(func
!= NULL
);
163 g_return_if_fail(purple_ssl_is_supported());
165 gsc
->recv_cb_data
= data
;
168 gsc
->inpa
= purple_input_add(gsc
->fd
, PURPLE_INPUT_READ
, recv_cb
, gsc
);
172 purple_ssl_strerror(PurpleSslErrorType error
)
175 case PURPLE_SSL_CONNECT_FAILED
:
176 return _("SSL Connection Failed");
177 case PURPLE_SSL_HANDSHAKE_FAILED
:
178 return _("SSL Handshake Failed");
179 case PURPLE_SSL_CERTIFICATE_INVALID
:
180 return _("SSL peer presented an invalid certificate");
182 purple_debug_warning("sslconn", "Unknown SSL error code %d\n", error
);
183 return _("Unknown SSL error");
187 PurpleSslConnection
*
188 purple_ssl_connect_fd(PurpleAccount
*account
, int fd
,
189 PurpleSslInputFunction func
,
190 PurpleSslErrorFunction error_func
,
193 return purple_ssl_connect_with_host_fd(account
, fd
, func
, error_func
, NULL
, data
);
196 PurpleSslConnection
*
197 purple_ssl_connect_with_host_fd(PurpleAccount
*account
, int fd
,
198 PurpleSslInputFunction func
,
199 PurpleSslErrorFunction error_func
,
203 PurpleSslConnection
*gsc
;
206 g_return_val_if_fail(fd
!= -1, NULL
);
207 g_return_val_if_fail(func
!= NULL
, NULL
);
208 g_return_val_if_fail(purple_ssl_is_supported(), NULL
);
210 if (!_ssl_initialized
)
216 gsc
= g_new0(PurpleSslConnection
, 1);
218 gsc
->connect_cb_data
= data
;
219 gsc
->connect_cb
= func
;
220 gsc
->error_cb
= error_func
;
223 gsc
->host
= g_strdup(host
);
225 /* TODO: Move this elsewhere */
226 gsc
->verifier
= purple_certificate_find_verifier("x509","tls_cached");
229 ops
= purple_ssl_get_ops();
230 ops
->connectfunc(gsc
);
232 return (PurpleSslConnection
*)gsc
;
236 purple_ssl_close(PurpleSslConnection
*gsc
)
240 g_return_if_fail(gsc
!= NULL
);
242 purple_request_close_with_handle(gsc
);
243 purple_notify_close_with_handle(gsc
);
245 ops
= purple_ssl_get_ops();
248 if (gsc
->connect_data
!= NULL
)
249 purple_proxy_connect_cancel(gsc
->connect_data
);
252 purple_input_remove(gsc
->inpa
);
262 purple_ssl_read(PurpleSslConnection
*gsc
, void *data
, size_t len
)
266 g_return_val_if_fail(gsc
!= NULL
, 0);
267 g_return_val_if_fail(data
!= NULL
, 0);
268 g_return_val_if_fail(len
> 0, 0);
270 ops
= purple_ssl_get_ops();
271 return (ops
->read
)(gsc
, data
, len
);
275 purple_ssl_write(PurpleSslConnection
*gsc
, const void *data
, size_t len
)
279 g_return_val_if_fail(gsc
!= NULL
, 0);
280 g_return_val_if_fail(data
!= NULL
, 0);
281 g_return_val_if_fail(len
> 0, 0);
283 ops
= purple_ssl_get_ops();
284 return (ops
->write
)(gsc
, data
, len
);
288 purple_ssl_get_peer_certificates(PurpleSslConnection
*gsc
)
292 g_return_val_if_fail(gsc
!= NULL
, NULL
);
294 ops
= purple_ssl_get_ops();
295 return (ops
->get_peer_certificates
)(gsc
);
299 purple_ssl_set_ops(PurpleSslOps
*ops
)
305 purple_ssl_get_ops(void)
311 purple_ssl_init(void)
313 /* Although purple_ssl_is_supported will do the initialization on
314 command, SSL plugins tend to register CertificateSchemes as well
315 as providing SSL ops. */
317 purple_debug_error("sslconn", "Unable to initialize SSL.\n");
322 purple_ssl_uninit(void)
326 if (!_ssl_initialized
)
329 ops
= purple_ssl_get_ops();
332 _ssl_initialized
= FALSE
;