Skip to content
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

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
@@ -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;
@@ -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) {
@@ -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;
@@ -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) {
@@ -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;
}

@@ -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;
}

@@ -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);
}

@@ -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};

@@ -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);

@@ -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
@@ -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;
}
@@ -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:
3 changes: 2 additions & 1 deletion libsofia-sip-ua/tport/ws.h
Original file line number Diff line number Diff line change
@@ -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 {