Bug Summary

File:core/network-openssl.c
Location:line 311, column 7
Description:Although the value stored to 'err' is used in the enclosing expression, the value is never actually read from 'err'

Annotated Source Code

1/*
2 network-ssl.c : SSL support
3
4 Copyright (C) 2002 vjt
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "module.h"
22#include "network.h"
23#include "misc.h"
24
25#ifdef HAVE_OPENSSL
26
27#include <openssl/crypto.h>
28#include <openssl/x509.h>
29#include <openssl/pem.h>
30#include <openssl/ssl.h>
31#include <openssl/err.h>
32
33/* ssl i/o channel object */
34typedef struct
35{
36 GIOChannel pad;
37 gint fd;
38 GIOChannel *giochan;
39 SSL *ssl;
40 SSL_CTX *ctx;
41 unsigned int verify:1;
42} GIOSSLChannel;
43
44static SSL_CTX *ssl_ctx = NULL((void *)0);
45
46static void irssi_ssl_free(GIOChannel *handle)
47{
48 GIOSSLChannel *chan = (GIOSSLChannel *)handle;
49 g_io_channel_unref(chan->giochan);
50 SSL_free(chan->ssl);
51 if (chan->ctx != ssl_ctx)
52 SSL_CTX_free(chan->ctx);
53 g_free(chan);
54}
55
56static gboolean irssi_ssl_verify(SSL *ssl, SSL_CTX *ctx, X509 *cert)
57{
58 if (SSL_get_verify_result(ssl) != X509_V_OK0) {
59 unsigned char md[EVP_MAX_MD_SIZE64];
60 unsigned int n;
61 char *str;
62
63 g_warning("Could not verify SSL servers certificate:")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "Could not verify SSL servers certificate:"
)
;
64 if ((str = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)) == NULL((void *)0))
65 g_warning(" Could not get subject-name from peer certificate")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, " Could not get subject-name from peer certificate"
)
;
66 else {
67 g_warning(" Subject : %s", str)g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, " Subject : %s", str
)
;
68 free(str);
69 }
70 if ((str = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)) == NULL((void *)0))
71 g_warning(" Could not get issuer-name from peer certificate")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, " Could not get issuer-name from peer certificate"
)
;
72 else {
73 g_warning(" Issuer : %s", str)g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, " Issuer : %s", str
)
;
74 free(str);
75 }
76 if (! X509_digest(cert, EVP_md5(), md, &n))
77 g_warning(" Could not get fingerprint from peer certificate")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, " Could not get fingerprint from peer certificate"
)
;
78 else {
79 char hex[] = "0123456789ABCDEF";
80 char fp[EVP_MAX_MD_SIZE64*3];
81 if (n < sizeof(fp)) {
82 unsigned int i;
83 for (i = 0; i < n; i++) {
84 fp[i*3+0] = hex[(md[i] >> 4) & 0xF];
85 fp[i*3+1] = hex[(md[i] >> 0) & 0xF];
86 fp[i*3+2] = i == n - 1 ? '\0' : ':';
87 }
88 g_warning(" MD5 Fingerprint : %s", fp)g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, " MD5 Fingerprint : %s"
, fp)
;
89 }
90 }
91 return FALSE(0);
92 }
93 return TRUE(!(0));
94}
95
96static GIOStatus irssi_ssl_read(GIOChannel *handle, gchar *buf, gsize len, gsize *ret, GError **gerr)
97{
98 GIOSSLChannel *chan = (GIOSSLChannel *)handle;
99 gint ret1, err;
100 const char *errstr;
101
102 ret1 = SSL_read(chan->ssl, buf, len);
103 if(ret1 <= 0)
104 {
105 *ret = 0;
106 err = SSL_get_error(chan->ssl, ret1);
107 if(err == SSL_ERROR_WANT_READ2 || err == SSL_ERROR_WANT_WRITE3)
108 return G_IO_STATUS_AGAIN;
109 else if(err == SSL_ERROR_ZERO_RETURN6)
110 return G_IO_STATUS_EOF;
111 else if (err == SSL_ERROR_SYSCALL5)
112 {
113 errstr = ERR_reason_error_string(ERR_get_error());
114 if (errstr == NULL((void *)0) && ret1 == -1)
115 errstr = strerror(errno(* __error()));
116 if (errstr == NULL((void *)0))
117 errstr = "server closed connection unexpectedly";
118 }
119 else
120 {
121 errstr = ERR_reason_error_string(ERR_get_error());
122 if (errstr == NULL((void *)0))
123 errstr = "unknown SSL error";
124 }
125 g_warning("SSL read error: %s", errstr)g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "SSL read error: %s"
, errstr)
;
126 *gerr = g_error_new_literal(G_IO_CHANNEL_ERRORg_io_channel_error_quark(), G_IO_CHANNEL_ERROR_FAILED,
127 errstr);
128 return G_IO_STATUS_ERROR;
129 }
130 else
131 {
132 *ret = ret1;
133 return G_IO_STATUS_NORMAL;
134 }
135 /*UNREACH*/
136 return G_IO_STATUS_ERROR;
137}
138
139static GIOStatus irssi_ssl_write(GIOChannel *handle, const gchar *buf, gsize len, gsize *ret, GError **gerr)
140{
141 GIOSSLChannel *chan = (GIOSSLChannel *)handle;
142 gint ret1, err;
143 const char *errstr;
144
145 ret1 = SSL_write(chan->ssl, (const char *)buf, len);
146 if(ret1 <= 0)
147 {
148 *ret = 0;
149 err = SSL_get_error(chan->ssl, ret1);
150 if(err == SSL_ERROR_WANT_READ2 || err == SSL_ERROR_WANT_WRITE3)
151 return G_IO_STATUS_AGAIN;
152 else if(err == SSL_ERROR_ZERO_RETURN6)
153 errstr = "server closed connection";
154 else if (err == SSL_ERROR_SYSCALL5)
155 {
156 errstr = ERR_reason_error_string(ERR_get_error());
157 if (errstr == NULL((void *)0) && ret1 == -1)
158 errstr = strerror(errno(* __error()));
159 if (errstr == NULL((void *)0))
160 errstr = "server closed connection unexpectedly";
161 }
162 else
163 {
164 errstr = ERR_reason_error_string(ERR_get_error());
165 if (errstr == NULL((void *)0))
166 errstr = "unknown SSL error";
167 }
168 g_warning("SSL write error: %s", errstr)g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "SSL write error: %s"
, errstr)
;
169 *gerr = g_error_new_literal(G_IO_CHANNEL_ERRORg_io_channel_error_quark(), G_IO_CHANNEL_ERROR_FAILED,
170 errstr);
171 return G_IO_STATUS_ERROR;
172 }
173 else
174 {
175 *ret = ret1;
176 return G_IO_STATUS_NORMAL;
177 }
178 /*UNREACH*/
179 return G_IO_STATUS_ERROR;
180}
181
182static GIOStatus irssi_ssl_seek(GIOChannel *handle, gint64 offset, GSeekType type, GError **gerr)
183{
184 GIOSSLChannel *chan = (GIOSSLChannel *)handle;
185
186 return chan->giochan->funcs->io_seek(handle, offset, type, gerr);
187}
188
189static GIOStatus irssi_ssl_close(GIOChannel *handle, GError **gerr)
190{
191 GIOSSLChannel *chan = (GIOSSLChannel *)handle;
192
193 return chan->giochan->funcs->io_close(handle, gerr);
194}
195
196static GSource *irssi_ssl_create_watch(GIOChannel *handle, GIOCondition cond)
197{
198 GIOSSLChannel *chan = (GIOSSLChannel *)handle;
199
200 return chan->giochan->funcs->io_create_watch(handle, cond);
201}
202
203static GIOStatus irssi_ssl_set_flags(GIOChannel *handle, GIOFlags flags, GError **gerr)
204{
205 GIOSSLChannel *chan = (GIOSSLChannel *)handle;
206
207 return chan->giochan->funcs->io_set_flags(handle, flags, gerr);
208}
209
210static GIOFlags irssi_ssl_get_flags(GIOChannel *handle)
211{
212 GIOSSLChannel *chan = (GIOSSLChannel *)handle;
213
214 return chan->giochan->funcs->io_get_flags(handle);
215}
216
217static GIOFuncs irssi_ssl_channel_funcs = {
218 irssi_ssl_read,
219 irssi_ssl_write,
220 irssi_ssl_seek,
221 irssi_ssl_close,
222 irssi_ssl_create_watch,
223 irssi_ssl_free,
224 irssi_ssl_set_flags,
225 irssi_ssl_get_flags
226};
227
228static gboolean irssi_ssl_init(void)
229{
230 SSL_library_init();
231 SSL_load_error_strings();
232
233 ssl_ctx = SSL_CTX_new(SSLv23_client_method());
234 if(!ssl_ctx)
235 {
236 g_error("Initialization of the SSL library failed")do { g_log (((gchar*) 0), G_LOG_LEVEL_ERROR, "Initialization of the SSL library failed"
); for (;;); } while (0)
;
237 return FALSE(0);
238 }
239
240 return TRUE(!(0));
241
242}
243
244static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, const char *mycert, const char *mypkey, const char *cafile, const char *capath, gboolean verify)
245{
246 GIOSSLChannel *chan;
247 GIOChannel *gchan;
248 int err, fd;
249 SSL *ssl;
250 SSL_CTX *ctx = NULL((void *)0);
251
252 g_return_val_if_fail(handle != NULL, NULL)do{ if (handle != ((void *)0)) { } else { g_return_if_fail_warning
(((gchar*) 0), __PRETTY_FUNCTION__, "handle != NULL"); return
(((void *)0)); }; }while (0)
;
253
254 if(!ssl_ctx && !irssi_ssl_init())
255 return NULL((void *)0);
256
257 if(!(fd = g_io_channel_unix_get_fd(handle)))
258 return NULL((void *)0);
259
260 if (mycert && *mycert) {
261 char *scert = NULL((void *)0), *spkey = NULL((void *)0);
262 if ((ctx = SSL_CTX_new(SSLv23_client_method())) == NULL((void *)0)) {
263 g_error("Could not allocate memory for SSL context")do { g_log (((gchar*) 0), G_LOG_LEVEL_ERROR, "Could not allocate memory for SSL context"
); for (;;); } while (0)
;
264 return NULL((void *)0);
265 }
266 scert = convert_home(mycert);
267 if (mypkey && *mypkey)
268 spkey = convert_home(mypkey);
269 if (! SSL_CTX_use_certificate_file(ctx, scert, SSL_FILETYPE_PEM1))
270 g_warning("Loading of client certificate '%s' failed", mycert)g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "Loading of client certificate '%s' failed"
, mycert)
;
271 else if (! SSL_CTX_use_PrivateKey_file(ctx, spkey ? spkey : scert, SSL_FILETYPE_PEM1))
272 g_warning("Loading of private key '%s' failed", mypkey ? mypkey : mycert)g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "Loading of private key '%s' failed"
, mypkey ? mypkey : mycert)
;
273 else if (! SSL_CTX_check_private_key(ctx))
274 g_warning("Private key does not match the certificate")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "Private key does not match the certificate"
)
;
275 g_free(scert);
276 g_free(spkey);
277 }
278
279 if ((cafile && *cafile) || (capath && *capath)) {
280 char *scafile = NULL((void *)0);
281 char *scapath = NULL((void *)0);
282 if (! ctx && (ctx = SSL_CTX_new(SSLv23_client_method())) == NULL((void *)0)) {
283 g_error("Could not allocate memory for SSL context")do { g_log (((gchar*) 0), G_LOG_LEVEL_ERROR, "Could not allocate memory for SSL context"
); for (;;); } while (0)
;
284 return NULL((void *)0);
285 }
286 if (cafile && *cafile)
287 scafile = convert_home(cafile);
288 if (capath && *capath)
289 scapath = convert_home(capath);
290 if (! SSL_CTX_load_verify_locations(ctx, scafile, scapath)) {
291 g_warning("Could not load CA list for verifying SSL server certificate")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "Could not load CA list for verifying SSL server certificate"
)
;
292 g_free(scafile);
293 g_free(scapath);
294 SSL_CTX_free(ctx);
295 return NULL((void *)0);
296 }
297 g_free(scafile);
298 g_free(scapath);
299 verify = TRUE(!(0));
300 }
301
302 if (ctx == NULL((void *)0))
303 ctx = ssl_ctx;
304
305 if(!(ssl = SSL_new(ctx)))
306 {
307 g_warning("Failed to allocate SSL structure")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "Failed to allocate SSL structure"
)
;
308 return NULL((void *)0);
309 }
310
311 if(!(err = SSL_set_fd(ssl, fd)))
Although the value stored to 'err' is used in the enclosing expression, the value is never actually read from 'err'
312 {
313 g_warning("Failed to associate socket to SSL stream")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "Failed to associate socket to SSL stream"
)
;
314 SSL_free(ssl);
315 if (ctx != ssl_ctx)
316 SSL_CTX_free(ctx);
317 return NULL((void *)0);
318 }
319
320 chan = g_new0(GIOSSLChannel, 1)((GIOSSLChannel *) g_malloc0 (((gsize) sizeof (GIOSSLChannel)
) * ((gsize) (1))))
;
321 chan->fd = fd;
322 chan->giochan = handle;
323 chan->ssl = ssl;
324 chan->ctx = ctx;
325 chan->verify = verify;
326
327 gchan = (GIOChannel *)chan;
328 gchan->funcs = &irssi_ssl_channel_funcs;
329 g_io_channel_init(gchan);
330 gchan->is_readable = gchan->is_writeable = TRUE(!(0));
331 gchan->use_buffer = FALSE(0);
332
333 return gchan;
334}
335
336GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify)
337{
338 GIOChannel *handle, *ssl_handle;
339
340 handle = net_connect_ip(ip, port, my_ip);
341 if (handle == NULL((void *)0))
342 return NULL((void *)0);
343 ssl_handle = irssi_ssl_get_iochannel(handle, cert, pkey, cafile, capath, verify);
344 if (ssl_handle == NULL((void *)0))
345 g_io_channel_unref(handle);
346 return ssl_handle;
347}
348
349int irssi_ssl_handshake(GIOChannel *handle)
350{
351 GIOSSLChannel *chan = (GIOSSLChannel *)handle;
352 int ret, err;
353 X509 *cert;
354 const char *errstr;
355
356 ret = SSL_connect(chan->ssl);
357 if (ret <= 0) {
358 err = SSL_get_error(chan->ssl, ret);
359 switch (err) {
360 case SSL_ERROR_WANT_READ2:
361 return 1;
362 case SSL_ERROR_WANT_WRITE3:
363 return 3;
364 case SSL_ERROR_ZERO_RETURN6:
365 g_warning("SSL handshake failed: %s", "server closed connection")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "SSL handshake failed: %s"
, "server closed connection")
;
366 return -1;
367 case SSL_ERROR_SYSCALL5:
368 errstr = ERR_reason_error_string(ERR_get_error());
369 if (errstr == NULL((void *)0) && ret == -1)
370 errstr = strerror(errno(* __error()));
371 g_warning("SSL handshake failed: %s", errstr != NULL ? errstr : "server closed connection unexpectedly")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "SSL handshake failed: %s"
, errstr != ((void *)0) ? errstr : "server closed connection unexpectedly"
)
;
372 return -1;
373 default:
374 errstr = ERR_reason_error_string(ERR_get_error());
375 g_warning("SSL handshake failed: %s", errstr != NULL ? errstr : "unknown SSL error")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "SSL handshake failed: %s"
, errstr != ((void *)0) ? errstr : "unknown SSL error")
;
376 return -1;
377 }
378 }
379
380 cert = SSL_get_peer_certificate(chan->ssl);
381 if (cert == NULL((void *)0)) {
382 g_warning("SSL server supplied no certificate")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "SSL server supplied no certificate"
)
;
383 return -1;
384 }
385 ret = !chan->verify || irssi_ssl_verify(chan->ssl, chan->ctx, cert);
386 X509_free(cert);
387 return ret ? 0 : -1;
388}
389
390#else /* HAVE_OPENSSL */
391
392GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify)
393{
394 g_warning("Connection failed: SSL support not enabled in this build.")g_log (((gchar*) 0), G_LOG_LEVEL_WARNING, "Connection failed: SSL support not enabled in this build."
)
;
395 errno(* __error()) = ENOSYS78;
396 return NULL((void *)0);
397}
398
399#endif /* ! HAVE_OPENSSL */