Hello,
I'm running 2 redundant freeradius servers backing a WPA2 cisco
wifi infrastructure. For authentification there is a TLS tunnel established
between the wifi client and one of the freeradius server.
The Freeradius servers are running NetBSD 5.0.2, which ships with a snapshot
of openssl 0.9.9.
Recently we started seeing crashes of radiusd, and it turned out to be
in libssl. The crashes are probably related to bogus packets sent by
a client, but still this should not cause the server to crash.
Although we have identified the client causing the crash it's not so easy
to reproduce, this seems to be related to specific radio conditions.
Here is the gdb backtrace from a radiusd -X (unfortunably I couldn't
convince radiusd do dump a core):
[peap] eaptls_verify returned 11
[peap] (other): before/accept initialization
[peap] TLS_accept: before/accept initialization
[peap] <<< TLS 1.0 Handshake [length 011c], ClientHello
[peap] TLS_accept: SSLv3 read client hello A
Program received signal SIGSEGV, Segmentation fault.
0xbbb9fb54 in ssl3_finish_mac () from /usr/lib/libssl.so.6
(gdb) where
#0 0xbbb9fb54 in ssl3_finish_mac () from /usr/lib/libssl.so.6
#1 0xbbb9c3b2 in ssl3_do_write () from /usr/lib/libssl.so.6
#2 0xbbb8c35e in ssl3_send_server_hello () from /usr/lib/libssl.so.6
#3 0xbbb8e74f in ssl3_accept () from /usr/lib/libssl.so.6
#4 0xbbb9d907 in ssl3_read_bytes () from /usr/lib/libssl.so.6
#5 0xbbb9e275 in ssl3_renegotiate_check () from /usr/lib/libssl.so.6
#6 0xbbba309e in SSL_read () from /usr/lib/libssl.so.6
#7 0xbb893539 in tls_handshake_recv ()
from /usr/pkg/lib/libfreeradius-eap-2.1.7.so
#8 0xbb892704 in eaptls_process ()
from /usr/pkg/lib/libfreeradius-eap-2.1.7.so
#9 0xbb877ffc in eappeap_authenticate ()
from /usr/pkg/lib/rlm_eap_peap-2.1.7.so
#10 0xbb898189 in eaptype_call () from /usr/pkg/lib/rlm_eap-2.1.7.so
#11 0xbb898dff in eaptype_select () from /usr/pkg/lib/rlm_eap-2.1.7.so
#12 0xbb897ab6 in eap_authenticate () from /usr/pkg/lib/rlm_eap-2.1.7.so
#13 0x0805f2eb in modcall ()
#14 0x0805c92e in indexed_modcall ()
#15 0x0805cba8 in module_authenticate ()
#16 0x0804ec9c in rad_authenticate ()
#17 0x080683da in radius_handle_request ()
#18 0x08061a44 in thread_pool_addrequest ()
#19 0x08065eb2 in event_socket_handler ()
---Type <return> to continue, or q <return> to quit---
#20 0xbbbe25ef in fr_event_loop ()
from /usr/pkg/lib/libfreeradius-radius-2.1.7.so
#21 0x0806680e in radius_event_process ()
#22 0x0805fe79 in main ()
The crash in ssl3_finish_mac() is caused by s->s3->handshake_dgst being NULL.
This can't happen in openssl 0.9.8, and I didn't find in the changelog or
sources anything suggesting that this could be fixed in 1.0.0
(I've applied the patch from secadv_20100324.txt but this didn't change
anything for this specific problem).
I'm now running with the attached patch, which test handshake_dgst
before using it in various places, which seems to be enough to prevent
the crash. but I've no idea if this is correct, or if the code
should ensure that handshake_dgst is never NULL in these code path
instead.
--
Manuel Bouyer <[email protected]>
NetBSD: 26 ans d'experience feront toujours la difference
--
Index: ssl/s3_enc.c
===================================================================
RCS file: /cvsroot/src/crypto/dist/openssl/ssl/Attic/s3_enc.c,v
retrieving revision 1.1.1.12
diff -u -p -u -r1.1.1.12 s3_enc.c
--- ssl/s3_enc.c 9 May 2008 21:34:44 -0000 1.1.1.12
+++ ssl/s3_enc.c 31 Mar 2010 10:49:02 -0000
@@ -570,7 +570,7 @@ void ssl3_finish_mac(SSL *s, const unsig
{
BIO_write (s->s3->handshake_buffer,(void *)buf,len);
}
- else
+ else if (s->s3->handshake_dgst != NULL)
{
int i;
for (i=0;i< SSL_MAX_DIGEST;i++)
Index: ssl/s3_srvr.c
===================================================================
RCS file: /cvsroot/src/crypto/dist/openssl/ssl/Attic/s3_srvr.c,v
retrieving revision 1.15.4.2
diff -u -p -u -r1.15.4.2 s3_srvr.c
--- ssl/s3_srvr.c 12 Jan 2010 09:07:51 -0000 1.15.4.2
+++ ssl/s3_srvr.c 31 Mar 2010 10:49:02 -0000
@@ -532,12 +532,14 @@ int ssl3_accept(SSL *s)
*/
if (s->s3->handshake_buffer)
ssl3_digest_cached_records(s);
- for (dgst_num=0;
dgst_num<SSL_MAX_DIGEST;dgst_num++)
- if (s->s3->handshake_dgst[dgst_num])
- {
-
s->method->ssl3_enc->cert_verify_mac(s,EVP_MD_CTX_type(s->s3->handshake_dgst[dgst_num]),&(s->s3->tmp.cert_verify_md[offset]));
-
offset+=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
- }
+ if (s->s3->handshake_dgst != NULL) {
+ for (dgst_num=0;
dgst_num<SSL_MAX_DIGEST;dgst_num++)
+ if
(s->s3->handshake_dgst[dgst_num])
+ {
+
s->method->ssl3_enc->cert_verify_mac(s,EVP_MD_CTX_type(s->s3->handshake_dgst[dgst_num]),&(s->s3->tmp.cert_verify_md[offset]));
+
offset+=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
+ }
+ }
}
break;
Index: ssl/t1_enc.c
===================================================================
RCS file: /cvsroot/src/crypto/dist/openssl/ssl/Attic/t1_enc.c,v
retrieving revision 1.1.1.12
diff -u -p -u -r1.1.1.12 t1_enc.c
--- ssl/t1_enc.c 9 May 2008 21:34:46 -0000 1.1.1.12
+++ ssl/t1_enc.c 31 Mar 2010 10:49:02 -0000
@@ -750,14 +750,16 @@ int tls1_cert_verify_mac(SSL *s, int md_
if (s->s3->handshake_buffer)
ssl3_digest_cached_records(s);
- for (i=0;i<SSL_MAX_DIGEST;i++)
- {
- if
(s->s3->handshake_dgst[i]&&EVP_MD_CTX_type(s->s3->handshake_dgst[i])==md_nid)
- {
- d=s->s3->handshake_dgst[i];
- break;
+ if (s->s3->handshake_dgst) {
+ for (i=0;i<SSL_MAX_DIGEST;i++)
+ {
+ if
(s->s3->handshake_dgst[i]&&EVP_MD_CTX_type(s->s3->handshake_dgst[i])==md_nid)
+ {
+ d=s->s3->handshake_dgst[i];
+ break;
+ }
}
- }
+ }
if (!d) {
SSLerr(SSL_F_TLS1_CERT_VERIFY_MAC,SSL_R_NO_REQUIRED_DIGEST);
return 0;
@@ -794,7 +796,8 @@ int tls1_final_finish_mac(SSL *s,
if (mask & s->s3->tmp.new_cipher->algorithm2)
{
unsigned int hashsize = EVP_MD_size(md);
- if (hashsize > (sizeof buf - (size_t)(q-buf)))
+ if (hashsize > (sizeof buf - (size_t)(q-buf)) ||
+ s->s3->handshake_dgst == NULL)
{
/* internal error: 'buf' is too small for this
cipersuite! */
err = 1;