Skip to content

[sofia-sip] fix issue 2283 by checking for SSL_ERROR_SSL and SSL_ERRO… #231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 46 additions & 10 deletions libsofia-sip-ua/tport/ws.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,9 @@ int ws_handshake(wsh_t *wsh)
ws_raw_write(wsh, respond, strlen(respond));
}

ws_close(wsh, WS_NONE);
if (wsh->sock != ws_sock_invalid) {
ws_close(wsh, WS_NONE);
}
}

return -1;
Expand All @@ -365,6 +367,10 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
if (wsh->ssl) {
do {
//ERR_clear_error();
if ((!SSL_has_pending(wsh->ssl)) && wsh->down) {
r = -1;
goto end;
}
r = SSL_read(wsh->ssl, data, bytes);

if (r < 0) {
Expand Down Expand Up @@ -456,12 +462,13 @@ int wss_error(wsh_t *wsh, int ssl_err, char const *who)
case SSL_ERROR_ZERO_RETURN:
return 0;

case SSL_ERROR_SSL:
case SSL_ERROR_SYSCALL:
wss_log_errors(1, who, ssl_err);
ERR_clear_error();
if (SSL_get_shutdown(wsh->ssl) & SSL_RECEIVED_SHUTDOWN)
return 0; /* EOS */
if (errno == 0)
return 0; /* EOS */
ws_close(wsh, WS_SSLERR);

errno = EIO;
return -1;
Expand All @@ -479,6 +486,11 @@ int wss_error(wsh_t *wsh, int ssl_err, char const *who)
static ssize_t ws_raw_read_blocking(wsh_t *wsh, char *data, size_t max_bytes, int max_retries)
{
ssize_t total_bytes_read = 0;

if (wsh->sock == ws_sock_invalid) {
return -3;
}

while (total_bytes_read < max_bytes && max_retries-- > 0) {
ssize_t bytes_read = ws_raw_read(wsh, data + total_bytes_read, max_bytes - total_bytes_read, WS_BLOCK);
if (bytes_read < 0) {
Expand Down Expand Up @@ -545,7 +557,7 @@ ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes)

if (!sanity) ssl_err = -56;

if (ssl_err) {
if (ssl_err <= 0) {
r = ssl_err;
}

Expand Down Expand Up @@ -694,11 +706,10 @@ int establish_logical_layer(wsh_t *wsh)

}

while (!wsh->down && !wsh->handshake) {
while (!wsh->down && !wsh->handshake && wsh->sock != ws_sock_invalid) {
int r = ws_handshake(wsh);

if (r < 0) {
wsh->down = 1;
return -1;
}

Expand Down Expand Up @@ -768,7 +779,11 @@ void ws_destroy(wsh_t *wsh)
return;
}

if (!wsh->down) {
if ((wsh->sock == ws_sock_invalid) && (!wsh->down)){
return;
}

if (!wsh->down && wsh->ssl) {
ws_close(wsh, WS_NONE);
}

Expand Down Expand Up @@ -805,7 +820,7 @@ ssize_t ws_close(wsh_t *wsh, int16_t reason)
wsh->uri = NULL;
}

if (reason && wsh->sock != ws_sock_invalid) {
if (reason && reason != WS_SSLERR && wsh->sock != ws_sock_invalid) {
uint16_t *u16;
uint8_t fr[4] = {WSOC_CLOSE | 0x80, 2, 0};

Expand All @@ -816,12 +831,29 @@ ssize_t ws_close(wsh_t *wsh, int16_t reason)

restore_socket(wsh->sock);

if (reason == WS_SSLERR) {
SSL_free(wsh->ssl);
wsh->ssl = NULL;
}

if (wsh->ssl) {
int code = 0;
int ssl_error = 0;
const char* buf = "0";
struct timeval tout = {5,0};

/* check if no fatal error occurs on connection */
if (SSL_get_shutdown(wsh->ssl)) {
goto ssl_finish_it;
}

// we're closing down, do not wait > 5 seoncds
if (setsockopt(SSL_get_wfd(wsh->ssl), SOL_SOCKET, SO_SNDTIMEO, &tout, sizeof(tout)) < 0) {
goto ssl_finish_it;
}
else if (setsockopt(SSL_get_wfd(wsh->ssl), SOL_SOCKET, SO_RCVTIMEO, &tout, sizeof(tout)) < 0) {
goto ssl_finish_it;
}
code = SSL_write(wsh->ssl, buf, 1);
ssl_error = SSL_get_error(wsh->ssl, code);

Expand All @@ -840,7 +872,7 @@ ssize_t ws_close(wsh_t *wsh, int16_t reason)
wsh->ssl = NULL;
}

if (wsh->close_sock && wsh->sock != ws_sock_invalid) {
if (wsh->close_sock && wsh->sock != ws_sock_invalid && reason != WS_SSLERR) {
#ifndef WIN32
close(wsh->sock);
#else
Expand Down Expand Up @@ -887,6 +919,10 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)

ll = establish_logical_layer(wsh);

if (ll == -1) {
ws_close(wsh, WS_SSLERR);
}

if (ll < 0) {
return ll;
}
Expand Down Expand Up @@ -922,7 +958,7 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
{
wsh->plen = wsh->buffer[1] & 0x7f;
*data = (uint8_t *) &wsh->buffer[2];
return ws_close(wsh, 1000);
return ws_close(wsh, WS_NORMAL);
}
break;
case WSOC_CONTINUATION:
Expand Down
3 changes: 2 additions & 1 deletion libsofia-sip-ua/tport/ws.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ typedef enum {
WS_NONE = 0,
WS_NORMAL = 1000,
WS_PROTO_ERR = 1002,
WS_DATA_TOO_BIG = 1009
WS_DATA_TOO_BIG = 1009,
WS_SSLERR = 1010
} ws_cause_t;

typedef enum {
Expand Down