diff options
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_sip.c | 58 | ||||
-rw-r--r-- | channels/sip/include/sip.h | 1 |
2 files changed, 42 insertions, 17 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index e1dfd5ddd..b2b3395c7 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2718,19 +2718,20 @@ static int sip_tls_read(struct sip_request *req, struct sip_request *reqcpy, str int authenticated, time_t start, struct sip_threadinfo *me) { int res, content_length, after_poll = 1, need_poll = 1; + size_t datalen = ast_str_strlen(req->data); char buf[1024] = ""; int timeout = -1; - - /* Read in headers one line at a time */ - while (ast_str_strlen(req->data) < 4 || strncmp(REQ_OFFSET_TO_STR(req, data->used - 4), "\r\n\r\n", 4)) { - if (!tcptls_session->client && !authenticated) { - if ((timeout = sip_check_authtimeout(start)) < 0) { - ast_debug(2, "SIP SSL server failed to determine authentication timeout\n"); + + /* Read in headers one line at a time */ + while (datalen < 4 || strncmp(REQ_OFFSET_TO_STR(req, data->used - 4), "\r\n\r\n", 4)) { + if (!tcptls_session->client && !authenticated) { + if ((timeout = sip_check_authtimeout(start)) < 0) { + ast_debug(2, "SIP TLS server failed to determine authentication timeout\n"); return -1; } if (timeout == 0) { - ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); + ast_debug(2, "SIP TLS server timed out\n"); return -1; } } else { @@ -2745,11 +2746,11 @@ static int sip_tls_read(struct sip_request *req, struct sip_request *reqcpy, str after_poll = 1; res = ast_wait_for_input(tcptls_session->fd, timeout); if (res < 0) { - ast_debug(2, "SIP TCP server :: ast_wait_for_input returned %d\n", res); + ast_debug(2, "SIP TLS server :: ast_wait_for_input returned %d\n", res); return -1; } else if (res == 0) { /* timeout */ - ast_debug(2, "SIP TCP server timed out\n"); + ast_debug(2, "SIP TLS server timed out\n"); return -1; } } @@ -2770,6 +2771,13 @@ static int sip_tls_read(struct sip_request *req, struct sip_request *reqcpy, str return -1; } ast_str_append(&req->data, 0, "%s", buf); + + datalen = ast_str_strlen(req->data); + if (datalen > SIP_MAX_PACKET_SIZE) { + ast_log(LOG_WARNING, "Rejecting TLS packet from '%s' because way too large: %zu\n", + ast_sockaddr_stringify(&tcptls_session->remote_address), datalen); + return -1; + } } copy_request(reqcpy, req); parse_request(reqcpy); @@ -2783,7 +2791,7 @@ static int sip_tls_read(struct sip_request *req, struct sip_request *reqcpy, str } if (timeout == 0) { - ast_debug(2, "SIP SSL server timed out\n"); + ast_debug(2, "SIP TLS server timed out\n"); return -1; } } else { @@ -2795,11 +2803,11 @@ static int sip_tls_read(struct sip_request *req, struct sip_request *reqcpy, str after_poll = 1; res = ast_wait_for_input(tcptls_session->fd, timeout); if (res < 0) { - ast_debug(2, "SIP TCP server :: ast_wait_for_input returned %d\n", res); + ast_debug(2, "SIP TLS server :: ast_wait_for_input returned %d\n", res); return -1; } else if (res == 0) { /* timeout */ - ast_debug(2, "SIP TCP server timed out\n"); + ast_debug(2, "SIP TLS server timed out\n"); return -1; } } @@ -2822,6 +2830,13 @@ static int sip_tls_read(struct sip_request *req, struct sip_request *reqcpy, str } content_length -= strlen(buf); ast_str_append(&req->data, 0, "%s", buf); + + datalen = ast_str_strlen(req->data); + if (datalen > SIP_MAX_PACKET_SIZE) { + ast_log(LOG_WARNING, "Rejecting TLS packet from '%s' because way too large: %zu\n", + ast_sockaddr_stringify(&tcptls_session->remote_address), datalen); + return -1; + } } } /*! \todo XXX If there's no Content-Length or if the content-length and what @@ -2995,6 +3010,8 @@ static int sip_tcp_read(struct sip_request *req, struct ast_tcptls_session_insta enum message_integrity message_integrity = MESSAGE_FRAGMENT; while (message_integrity == MESSAGE_FRAGMENT) { + size_t datalen; + if (ast_str_strlen(tcptls_session->overflow_buf) == 0) { char readbuf[4097]; int timeout; @@ -3034,6 +3051,13 @@ static int sip_tcp_read(struct sip_request *req, struct ast_tcptls_session_insta ast_str_append(&req->data, 0, "%s", ast_str_buffer(tcptls_session->overflow_buf)); ast_str_reset(tcptls_session->overflow_buf); } + + datalen = ast_str_strlen(req->data); + if (datalen > SIP_MAX_PACKET_SIZE) { + ast_log(LOG_WARNING, "Rejecting TCP packet from '%s' because way too large: %zu\n", + ast_sockaddr_stringify(&tcptls_session->remote_address), datalen); + return -1; + } message_integrity = check_message_integrity(&req->data, &tcptls_session->overflow_buf); } @@ -3105,7 +3129,7 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s } me->threadid = pthread_self(); - ast_debug(2, "Starting thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); + ast_debug(2, "Starting thread for %s server\n", tcptls_session->ssl ? "TLS" : "TCP"); /* set up pollfd to watch for reads on both the socket and the alert_pipe */ fds[0].fd = tcptls_session->fd; @@ -3139,7 +3163,7 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s } if (timeout == 0) { - ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); + ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "TLS": "TCP"); goto cleanup; } } else { @@ -3149,11 +3173,11 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s if (ast_str_strlen(tcptls_session->overflow_buf) == 0) { res = ast_poll(fds, 2, timeout); /* polls for both socket and alert_pipe */ if (res < 0) { - ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res); + ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "TLS": "TCP", res); goto cleanup; } else if (res == 0) { /* timeout */ - ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); + ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "TLS": "TCP"); goto cleanup; } } @@ -3235,7 +3259,7 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s } } - ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); + ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "TLS" : "TCP"); cleanup: if (tcptls_session && !tcptls_session->client && !authenticated) { diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index 9a818553b..f51ac7749 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -101,6 +101,7 @@ #define SIP_MAX_HEADERS 64 /*!< Max amount of SIP headers to read */ #define SIP_MAX_LINES 256 /*!< Max amount of lines in SIP attachment (like SDP) */ +#define SIP_MAX_PACKET_SIZE 20480 /*!< Max SIP packet size */ #define SIP_MIN_PACKET 4096 /*!< Initialize size of memory to allocate for packets */ #define MAX_HISTORY_ENTRIES 50 /*!< Max entires in the history list for a sip_pvt */ |