Index: channels/sip/include/sip.h =================================================================== --- channels/sip/include/sip.h (revision 376119) +++ channels/sip/include/sip.h (working copy) @@ -96,6 +96,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 */ Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 376119) +++ channels/chan_sip.c (working copy) @@ -2523,20 +2523,21 @@ static int sip_tls_read(struct sip_request *req, struct ast_tcptls_session_instance *tcptls_session, 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); struct sip_request reqcpy = { 0, }; 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)) { + 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 SSL server failed to determine authentication timeout\n"); + 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 { @@ -2551,11 +2552,11 @@ 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; } } @@ -2576,6 +2577,13 @@ 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); @@ -2589,7 +2597,7 @@ } if (timeout == 0) { - ast_debug(2, "SIP SSL server timed out\n"); + ast_debug(2, "SIP TLS server timed out\n"); return -1; } } else { @@ -2601,11 +2609,11 @@ 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; } } @@ -2628,6 +2636,13 @@ } 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 @@ -2801,6 +2816,8 @@ 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; @@ -2840,6 +2857,13 @@ 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); } @@ -2911,7 +2935,7 @@ } 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; @@ -2945,7 +2969,7 @@ } 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 { @@ -2955,11 +2979,11 @@ 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; } } @@ -3041,7 +3065,7 @@ } } - 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) {