Fix alert handling.

Fix OpenSSL 0.9.8 alert handling.

PR#3038
This commit is contained in:
mancha
2014-03-27 00:47:14 +00:00
committed by Dr. Stephen Henson
parent d471adf351
commit a375025e4d
9 changed files with 126 additions and 46 deletions

View File

@@ -4,6 +4,12 @@
Changes between 0.9.8y and 0.9.8za [xx XXX xxxx] Changes between 0.9.8y and 0.9.8za [xx XXX xxxx]
*) Fix handling of warning-level alerts in SSL23 client mode so they
don't cause client-side termination (eg. on SNI unrecognized_name
warnings). Add client and server support for six additional alerts
per RFC 6066 and RFC 4279.
[mancha]
*) Add option SSL_OP_SAFARI_ECDHE_ECDSA_BUG (part of SSL_OP_ALL) which *) Add option SSL_OP_SAFARI_ECDHE_ECDSA_BUG (part of SSL_OP_ALL) which
avoids preferring ECDHE-ECDSA ciphers when the client appears to be avoids preferring ECDHE-ECDSA ciphers when the client appears to be
Safari on OS X. Safari on OS X 10.8..10.8.3 advertises support for Safari on OS X. Safari on OS X 10.8..10.8.3 advertises support for

View File

@@ -518,6 +518,24 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void *
case 100: case 100:
str_details2 = " no_renegotiation"; str_details2 = " no_renegotiation";
break; break;
case 110:
str_details2 = " unsupported_extension";
break;
case 111:
str_details2 = " certificate_unobtainable";
break;
case 112:
str_details2 = " unrecognized_name";
break;
case 113:
str_details2 = " bad_certificate_status_response";
break;
case 114:
str_details2 = " bad_certificate_hash_value";
break;
case 115:
str_details2 = " unknown_psk_identity";
break;
} }
} }
} }

View File

@@ -71,6 +71,11 @@ R SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071
R SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 R SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080
R SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 R SSL_R_TLSV1_ALERT_USER_CANCELLED 1090
R SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 R SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100
R SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110
R SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111
R SSL_R_TLSV1_UNRECOGNIZED_NAME 1112
R SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113
R SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114
R RSAREF_R_CONTENT_ENCODING 0x0400 R RSAREF_R_CONTENT_ENCODING 0x0400
R RSAREF_R_DATA 0x0401 R RSAREF_R_DATA 0x0401

View File

@@ -509,7 +509,7 @@ static int ssl23_get_server_hello(SSL *s)
/* use special padding (SSL 3.0 draft/RFC 2246, App. E.2) */ /* use special padding (SSL 3.0 draft/RFC 2246, App. E.2) */
s->s2->ssl2_rollback=1; s->s2->ssl2_rollback=1;
/* setup the 5 bytes we have read so we get them from /* setup the 7 bytes we have read so we get them from
* the sslv2 buffer */ * the sslv2 buffer */
s->rstate=SSL_ST_READ_HEADER; s->rstate=SSL_ST_READ_HEADER;
s->packet_length=n; s->packet_length=n;
@@ -525,27 +525,13 @@ static int ssl23_get_server_hello(SSL *s)
s->handshake_func=s->method->ssl_connect; s->handshake_func=s->method->ssl_connect;
#endif #endif
} }
else if ((p[0] == SSL3_RT_HANDSHAKE) && else if (p[1] == SSL3_VERSION_MAJOR &&
(p[1] == SSL3_VERSION_MAJOR) && ((p[2] == SSL3_VERSION_MINOR) ||
((p[2] == SSL3_VERSION_MINOR) || (p[2] == TLS1_VERSION_MINOR)) &&
(p[2] == TLS1_VERSION_MINOR)) && ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) ||
(p[5] == SSL3_MT_SERVER_HELLO)) (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2)))
{ {
/* we have sslv3 or tls1 */ /* we have sslv3 or tls1 (server hello or alert) */
if (!ssl_init_wbio_buffer(s,1)) goto err;
/* we are in this state */
s->state=SSL3_ST_CR_SRVR_HELLO_A;
/* put the 5 bytes we have read into the input buffer
* for SSLv3 */
s->rstate=SSL_ST_READ_HEADER;
s->packet_length=n;
s->packet= &(s->s3->rbuf.buf[0]);
memcpy(s->packet,buf,n);
s->s3->rbuf.left=n;
s->s3->rbuf.offset=0;
if ((p[2] == SSL3_VERSION_MINOR) && if ((p[2] == SSL3_VERSION_MINOR) &&
!(s->options & SSL_OP_NO_SSLv3)) !(s->options & SSL_OP_NO_SSLv3))
@@ -572,35 +558,52 @@ static int ssl23_get_server_hello(SSL *s)
SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
goto err; goto err;
} }
s->handshake_func=s->method->ssl_connect;
}
else if ((p[0] == SSL3_RT_ALERT) &&
(p[1] == SSL3_VERSION_MAJOR) &&
((p[2] == SSL3_VERSION_MINOR) ||
(p[2] == TLS1_VERSION_MINOR)) &&
(p[3] == 0) &&
(p[4] == 2))
{
void (*cb)(const SSL *ssl,int type,int val)=NULL;
int j;
/* An alert */ if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING)
if (s->info_callback != NULL)
cb=s->info_callback;
else if (s->ctx->info_callback != NULL)
cb=s->ctx->info_callback;
i=p[5];
if (cb != NULL)
{ {
j=(i<<8)|p[6]; /* fatal alert */
cb(s,SSL_CB_READ_ALERT,j);
void (*cb)(const SSL *ssl,int type,int val)=NULL;
int j;
if (s->info_callback != NULL)
cb=s->info_callback;
else if (s->ctx->info_callback != NULL)
cb=s->ctx->info_callback;
i=p[5];
if (cb != NULL)
{
j=(i<<8)|p[6];
cb(s,SSL_CB_READ_ALERT,j);
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_ALERT, p+5, 2, s, s->msg_callback_arg);
s->rwstate=SSL_NOTHING;
SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_AD_REASON_OFFSET+p[6]);
goto err;
} }
s->rwstate=SSL_NOTHING; if (!ssl_init_wbio_buffer(s,1)) goto err;
SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_AD_REASON_OFFSET+p[6]);
goto err; /* we are in this state */
s->state=SSL3_ST_CR_SRVR_HELLO_A;
/* put the 7 bytes we have read into the input buffer
* for SSLv3 */
s->rstate=SSL_ST_READ_HEADER;
s->packet_length=n;
if (s->s3->rbuf.buf == NULL)
if (!ssl3_setup_buffers(s))
goto err;
s->packet= &(s->s3->rbuf.buf[0]);
memcpy(s->packet,buf,n);
s->s3->rbuf.left=n;
s->s3->rbuf.offset=0;
s->handshake_func=s->method->ssl_connect;
} }
else else
{ {

View File

@@ -758,6 +758,12 @@ int ssl3_alert_code(int code)
case SSL_AD_INTERNAL_ERROR: return(SSL3_AD_HANDSHAKE_FAILURE); case SSL_AD_INTERNAL_ERROR: return(SSL3_AD_HANDSHAKE_FAILURE);
case SSL_AD_USER_CANCELLED: return(SSL3_AD_HANDSHAKE_FAILURE); case SSL_AD_USER_CANCELLED: return(SSL3_AD_HANDSHAKE_FAILURE);
case SSL_AD_NO_RENEGOTIATION: return(-1); /* Don't send it :-) */ case SSL_AD_NO_RENEGOTIATION: return(-1); /* Don't send it :-) */
case SSL_AD_UNSUPPORTED_EXTENSION: return(SSL3_AD_HANDSHAKE_FAILURE);
case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(SSL3_AD_HANDSHAKE_FAILURE);
case SSL_AD_UNRECOGNIZED_NAME: return(SSL3_AD_HANDSHAKE_FAILURE);
case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(SSL3_AD_HANDSHAKE_FAILURE);
case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(SSL3_AD_HANDSHAKE_FAILURE);
case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
default: return(-1); default: return(-1);
} }
} }

View File

@@ -1207,6 +1207,8 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
#define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE #define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
#define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME #define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE #define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
#define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
#define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */
#define SSL_ERROR_NONE 0 #define SSL_ERROR_NONE 0
#define SSL_ERROR_SSL 1 #define SSL_ERROR_SSL 1
@@ -2077,6 +2079,11 @@ void ERR_load_SSL_strings(void);
#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022 #define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022
#define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 #define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048
#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 #define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090
#define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114
#define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113
#define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111
#define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112
#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110
#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232 #define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232
#define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 227 #define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 227
#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233 #define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233

View File

@@ -475,6 +475,11 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_TLSV1_ALERT_RECORD_OVERFLOW),"tlsv1 alert record overflow"}, {ERR_REASON(SSL_R_TLSV1_ALERT_RECORD_OVERFLOW),"tlsv1 alert record overflow"},
{ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA),"tlsv1 alert unknown ca"}, {ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA),"tlsv1 alert unknown ca"},
{ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED),"tlsv1 alert user cancelled"}, {ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED),"tlsv1 alert user cancelled"},
{ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE),"tlsv1 bad certificate hash value"},
{ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE),"tlsv1 bad certificate status response"},
{ERR_REASON(SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE),"tlsv1 certificate unobtainable"},
{ERR_REASON(SSL_R_TLSV1_UNRECOGNIZED_NAME),"tlsv1 unrecognized name"},
{ERR_REASON(SSL_R_TLSV1_UNSUPPORTED_EXTENSION),"tlsv1 unsupported extension"},
{ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),"tls client cert req with anon cipher"}, {ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),"tls client cert req with anon cipher"},
{ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"}, {ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"},
{ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"}, {ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"},

View File

@@ -414,6 +414,12 @@ const char *SSL_alert_desc_string(int value)
case TLS1_AD_INTERNAL_ERROR: str="IE"; break; case TLS1_AD_INTERNAL_ERROR: str="IE"; break;
case TLS1_AD_USER_CANCELLED: str="US"; break; case TLS1_AD_USER_CANCELLED: str="US"; break;
case TLS1_AD_NO_RENEGOTIATION: str="NR"; break; case TLS1_AD_NO_RENEGOTIATION: str="NR"; break;
case TLS1_AD_UNSUPPORTED_EXTENSION: str="UE"; break;
case TLS1_AD_CERTIFICATE_UNOBTAINABLE: str="CO"; break;
case TLS1_AD_UNRECOGNIZED_NAME: str="UN"; break;
case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: str="BR"; break;
case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: str="BH"; break;
case TLS1_AD_UNKNOWN_PSK_IDENTITY: str="UP"; break;
default: str="UK"; break; default: str="UK"; break;
} }
return(str); return(str);
@@ -497,6 +503,24 @@ const char *SSL_alert_desc_string_long(int value)
case TLS1_AD_NO_RENEGOTIATION: case TLS1_AD_NO_RENEGOTIATION:
str="no renegotiation"; str="no renegotiation";
break; break;
case TLS1_AD_UNSUPPORTED_EXTENSION:
str="unsupported extension";
break;
case TLS1_AD_CERTIFICATE_UNOBTAINABLE:
str="certificate unobtainable";
break;
case TLS1_AD_UNRECOGNIZED_NAME:
str="unrecognized name";
break;
case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
str="bad certificate status response";
break;
case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
str="bad certificate hash value";
break;
case TLS1_AD_UNKNOWN_PSK_IDENTITY:
str="unknown PSK identity";
break;
default: str="unknown"; break; default: str="unknown"; break;
} }
return(str); return(str);

View File

@@ -853,6 +853,12 @@ int tls1_alert_code(int code)
case SSL_AD_INTERNAL_ERROR: return(TLS1_AD_INTERNAL_ERROR); case SSL_AD_INTERNAL_ERROR: return(TLS1_AD_INTERNAL_ERROR);
case SSL_AD_USER_CANCELLED: return(TLS1_AD_USER_CANCELLED); case SSL_AD_USER_CANCELLED: return(TLS1_AD_USER_CANCELLED);
case SSL_AD_NO_RENEGOTIATION: return(TLS1_AD_NO_RENEGOTIATION); case SSL_AD_NO_RENEGOTIATION: return(TLS1_AD_NO_RENEGOTIATION);
case SSL_AD_UNSUPPORTED_EXTENSION: return(TLS1_AD_UNSUPPORTED_EXTENSION);
case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(TLS1_AD_CERTIFICATE_UNOBTAINABLE);
case SSL_AD_UNRECOGNIZED_NAME: return(TLS1_AD_UNRECOGNIZED_NAME);
case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE);
case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE #ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return
(DTLS1_AD_MISSING_HANDSHAKE_MESSAGE); (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);