Skip to content

Commit 9a38e92

Browse files
davidbenagl
authored andcommitted
Return SSL_ERROR_SYSCALL on unclean EOF.
This regressed in fcf2583. 0 return code on unclean shutdown means the underlying BIO returned EOF, didn't push any error code, but we haven't seen close_notify yet. The intent seems to be that you go check errno or some BIO-specific equivalent if you care about close_notify. Make sure test code routes all SSL_read return codes through SSL_get_error since that's supposed to work in all cases. (Note that rv == 0 can still give SSL_ERROR_SSL if the error queue is not empty.) Change-Id: I45bf9614573f876d93419ce169a4e0d9ceea9052 Reviewed-on: https://boringssl-review.googlesource.com/2981 Reviewed-by: Adam Langley <[email protected]>
1 parent 1e52eca commit 9a38e92

File tree

2 files changed

+42
-21
lines changed

2 files changed

+42
-21
lines changed

ssl/ssl_lib.c

+10-5
Original file line numberDiff line numberDiff line change
@@ -2251,13 +2251,18 @@ int SSL_get_error(const SSL *s, int i) {
22512251
return SSL_ERROR_SSL;
22522252
}
22532253

2254-
if (i == 0 && (s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
2255-
(s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) {
2256-
return SSL_ERROR_ZERO_RETURN;
2254+
if (i == 0) {
2255+
if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
2256+
(s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) {
2257+
/* The socket was cleanly shut down with a close_notify. */
2258+
return SSL_ERROR_ZERO_RETURN;
2259+
}
2260+
/* An EOF was observed which violates the protocol, and the underlying
2261+
* transport does not participate in the error queue. Bubble up to the
2262+
* caller. */
2263+
return SSL_ERROR_SYSCALL;
22572264
}
22582265

2259-
assert(i < 0);
2260-
22612266
if (SSL_want_session(s)) {
22622267
return SSL_ERROR_PENDING_SESSION;
22632268
}

ssl/test/bssl_shim.cc

+32-16
Original file line numberDiff line numberDiff line change
@@ -656,25 +656,41 @@ static int do_exchange(SSL_SESSION **out_session,
656656
do {
657657
n = SSL_read(ssl, buf, sizeof(buf));
658658
} while (config->async && retry_async(ssl, n, bio));
659-
if (n < 0) {
659+
int err = SSL_get_error(ssl, n);
660+
if (err == SSL_ERROR_ZERO_RETURN ||
661+
(n == 0 && err == SSL_ERROR_SYSCALL)) {
662+
if (n != 0) {
663+
fprintf(stderr, "Invalid SSL_get_error output\n");
664+
return 3;
665+
}
666+
/* Accept shutdowns with or without close_notify.
667+
* TODO(davidben): Write tests which distinguish these two cases. */
668+
break;
669+
} else if (err != SSL_ERROR_NONE) {
670+
if (n > 0) {
671+
fprintf(stderr, "Invalid SSL_get_error output\n");
672+
return 3;
673+
}
660674
SSL_free(ssl);
661675
BIO_print_errors_fp(stdout);
662676
return 3;
663-
} else if (n == 0) {
664-
break;
665-
} else {
666-
for (int i = 0; i < n; i++) {
667-
buf[i] ^= 0xff;
668-
}
669-
int w;
670-
do {
671-
w = SSL_write(ssl, buf, n);
672-
} while (config->async && retry_async(ssl, w, bio));
673-
if (w != n) {
674-
SSL_free(ssl);
675-
BIO_print_errors_fp(stdout);
676-
return 4;
677-
}
677+
}
678+
/* Successfully read data. */
679+
if (n <= 0) {
680+
fprintf(stderr, "Invalid SSL_get_error output\n");
681+
return 3;
682+
}
683+
for (int i = 0; i < n; i++) {
684+
buf[i] ^= 0xff;
685+
}
686+
int w;
687+
do {
688+
w = SSL_write(ssl, buf, n);
689+
} while (config->async && retry_async(ssl, w, bio));
690+
if (w != n) {
691+
SSL_free(ssl);
692+
BIO_print_errors_fp(stdout);
693+
return 4;
678694
}
679695
}
680696
}

0 commit comments

Comments
 (0)