diff options
Diffstat (limited to 'src/lib/libssl/ssl_pkt.c')
| -rw-r--r-- | src/lib/libssl/ssl_pkt.c | 122 |
1 files changed, 71 insertions, 51 deletions
diff --git a/src/lib/libssl/ssl_pkt.c b/src/lib/libssl/ssl_pkt.c index 3374713644..e3b2034eb4 100644 --- a/src/lib/libssl/ssl_pkt.c +++ b/src/lib/libssl/ssl_pkt.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ssl_pkt.c,v 1.53 2022/02/05 14:54:10 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_pkt.c,v 1.54 2022/02/21 18:22:20 jsing Exp $ */ |
| 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| @@ -685,6 +685,73 @@ ssl3_write_pending(SSL *s, int type, const unsigned char *buf, unsigned int len) | |||
| 685 | } | 685 | } |
| 686 | } | 686 | } |
| 687 | 687 | ||
| 688 | int | ||
| 689 | ssl3_read_alert(SSL *s) | ||
| 690 | { | ||
| 691 | SSL3_RECORD_INTERNAL *rr = &s->s3->rrec; | ||
| 692 | uint8_t alert_level, alert_descr; | ||
| 693 | |||
| 694 | /* | ||
| 695 | * TLSv1.2 permits an alert to be fragmented across multiple records or | ||
| 696 | * for multiple alerts to be be coalesced into a single alert record. | ||
| 697 | * In the case of DTLS, there is no way to reassemble an alert | ||
| 698 | * fragmented across multiple records, hence a full alert must be | ||
| 699 | * available in the record. | ||
| 700 | */ | ||
| 701 | while (rr->length > 0 && | ||
| 702 | s->s3->alert_fragment_len < sizeof(s->s3->alert_fragment)) { | ||
| 703 | s->s3->alert_fragment[s->s3->alert_fragment_len++] = | ||
| 704 | rr->data[rr->off++]; | ||
| 705 | rr->length--; | ||
| 706 | } | ||
| 707 | if (s->s3->alert_fragment_len < sizeof(s->s3->alert_fragment)) { | ||
| 708 | if (SSL_is_dtls(s)) { | ||
| 709 | SSLerror(s, SSL_R_BAD_LENGTH); | ||
| 710 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | ||
| 711 | return -1; | ||
| 712 | } | ||
| 713 | return 1; | ||
| 714 | } | ||
| 715 | |||
| 716 | ssl_msg_callback(s, 0, SSL3_RT_ALERT, s->s3->alert_fragment, 2); | ||
| 717 | |||
| 718 | alert_level = s->s3->alert_fragment[0]; | ||
| 719 | alert_descr = s->s3->alert_fragment[1]; | ||
| 720 | s->s3->alert_fragment_len = 0; | ||
| 721 | |||
| 722 | ssl_info_callback(s, SSL_CB_READ_ALERT, | ||
| 723 | (alert_level << 8) | alert_descr); | ||
| 724 | |||
| 725 | if (alert_level == SSL3_AL_WARNING) { | ||
| 726 | s->s3->warn_alert = alert_descr; | ||
| 727 | if (alert_descr == SSL_AD_CLOSE_NOTIFY) { | ||
| 728 | s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; | ||
| 729 | return 0; | ||
| 730 | } | ||
| 731 | /* We requested renegotiation and the peer rejected it. */ | ||
| 732 | if (alert_descr == SSL_AD_NO_RENEGOTIATION) { | ||
| 733 | SSLerror(s, SSL_R_NO_RENEGOTIATION); | ||
| 734 | ssl3_send_alert(s, SSL3_AL_FATAL, | ||
| 735 | SSL_AD_HANDSHAKE_FAILURE); | ||
| 736 | return -1; | ||
| 737 | } | ||
| 738 | } else if (alert_level == SSL3_AL_FATAL) { | ||
| 739 | s->internal->rwstate = SSL_NOTHING; | ||
| 740 | s->s3->fatal_alert = alert_descr; | ||
| 741 | SSLerror(s, SSL_AD_REASON_OFFSET + alert_descr); | ||
| 742 | ERR_asprintf_error_data("SSL alert number %d", alert_descr); | ||
| 743 | s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; | ||
| 744 | SSL_CTX_remove_session(s->ctx, s->session); | ||
| 745 | return 0; | ||
| 746 | } else { | ||
| 747 | SSLerror(s, SSL_R_UNKNOWN_ALERT_TYPE); | ||
| 748 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); | ||
| 749 | return -1; | ||
| 750 | } | ||
| 751 | |||
| 752 | return 1; | ||
| 753 | } | ||
| 754 | |||
| 688 | /* Return up to 'len' payload bytes received in 'type' records. | 755 | /* Return up to 'len' payload bytes received in 'type' records. |
| 689 | * 'type' is one of the following: | 756 | * 'type' is one of the following: |
| 690 | * | 757 | * |
| @@ -875,10 +942,6 @@ ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) | |||
| 875 | dest_maxlen = sizeof s->s3->handshake_fragment; | 942 | dest_maxlen = sizeof s->s3->handshake_fragment; |
| 876 | dest = s->s3->handshake_fragment; | 943 | dest = s->s3->handshake_fragment; |
| 877 | dest_len = &s->s3->handshake_fragment_len; | 944 | dest_len = &s->s3->handshake_fragment_len; |
| 878 | } else if (rr->type == SSL3_RT_ALERT) { | ||
| 879 | dest_maxlen = sizeof s->s3->alert_fragment; | ||
| 880 | dest = s->s3->alert_fragment; | ||
| 881 | dest_len = &s->s3->alert_fragment_len; | ||
| 882 | } | 945 | } |
| 883 | if (dest_maxlen > 0) { | 946 | if (dest_maxlen > 0) { |
| 884 | /* available space in 'dest' */ | 947 | /* available space in 'dest' */ |
| @@ -966,53 +1029,10 @@ ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) | |||
| 966 | ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); | 1029 | ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); |
| 967 | goto start; | 1030 | goto start; |
| 968 | } | 1031 | } |
| 969 | if (s->s3->alert_fragment_len >= 2) { | ||
| 970 | int alert_level = s->s3->alert_fragment[0]; | ||
| 971 | int alert_descr = s->s3->alert_fragment[1]; | ||
| 972 | |||
| 973 | s->s3->alert_fragment_len = 0; | ||
| 974 | |||
| 975 | ssl_msg_callback(s, 0, SSL3_RT_ALERT, | ||
| 976 | s->s3->alert_fragment, 2); | ||
| 977 | |||
| 978 | ssl_info_callback(s, SSL_CB_READ_ALERT, | ||
| 979 | (alert_level << 8) | alert_descr); | ||
| 980 | |||
| 981 | if (alert_level == SSL3_AL_WARNING) { | ||
| 982 | s->s3->warn_alert = alert_descr; | ||
| 983 | if (alert_descr == SSL_AD_CLOSE_NOTIFY) { | ||
| 984 | s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; | ||
| 985 | return (0); | ||
| 986 | } | ||
| 987 | /* This is a warning but we receive it if we requested | ||
| 988 | * renegotiation and the peer denied it. Terminate with | ||
| 989 | * a fatal alert because if application tried to | ||
| 990 | * renegotiatie it presumably had a good reason and | ||
| 991 | * expects it to succeed. | ||
| 992 | * | ||
| 993 | * In future we might have a renegotiation where we | ||
| 994 | * don't care if the peer refused it where we carry on. | ||
| 995 | */ | ||
| 996 | else if (alert_descr == SSL_AD_NO_RENEGOTIATION) { | ||
| 997 | al = SSL_AD_HANDSHAKE_FAILURE; | ||
| 998 | SSLerror(s, SSL_R_NO_RENEGOTIATION); | ||
| 999 | goto fatal_err; | ||
| 1000 | } | ||
| 1001 | } else if (alert_level == SSL3_AL_FATAL) { | ||
| 1002 | s->internal->rwstate = SSL_NOTHING; | ||
| 1003 | s->s3->fatal_alert = alert_descr; | ||
| 1004 | SSLerror(s, SSL_AD_REASON_OFFSET + alert_descr); | ||
| 1005 | ERR_asprintf_error_data("SSL alert number %d", | ||
| 1006 | alert_descr); | ||
| 1007 | s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; | ||
| 1008 | SSL_CTX_remove_session(s->ctx, s->session); | ||
| 1009 | return (0); | ||
| 1010 | } else { | ||
| 1011 | al = SSL_AD_ILLEGAL_PARAMETER; | ||
| 1012 | SSLerror(s, SSL_R_UNKNOWN_ALERT_TYPE); | ||
| 1013 | goto fatal_err; | ||
| 1014 | } | ||
| 1015 | 1032 | ||
| 1033 | if (rr->type == SSL3_RT_ALERT) { | ||
| 1034 | if ((ret = ssl3_read_alert(s)) <= 0) | ||
| 1035 | return ret; | ||
| 1016 | goto start; | 1036 | goto start; |
| 1017 | } | 1037 | } |
| 1018 | 1038 | ||
