diff options
-rw-r--r-- | channels/chan_sip.c | 58 | ||||
-rw-r--r-- | channels/sip/include/sip.h | 1 | ||||
-rw-r--r-- | main/http.c | 20 | ||||
-rw-r--r-- | res/res_jabber.c | 5 |
4 files changed, 60 insertions, 24 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 */ diff --git a/main/http.c b/main/http.c index 44148edf8..fc2931290 100644 --- a/main/http.c +++ b/main/http.c @@ -611,6 +611,7 @@ struct ast_variable *ast_http_get_post_vars( int content_length = 0; struct ast_variable *v, *post_vars=NULL, *prev = NULL; char *buf, *var, *val; + int res; for (v = headers; v; v = v->next) { if (!strcasecmp(v->name, "Content-Type")) { @@ -623,20 +624,28 @@ struct ast_variable *ast_http_get_post_vars( for (v = headers; v; v = v->next) { if (!strcasecmp(v->name, "Content-Length")) { - content_length = atoi(v->value) + 1; + content_length = atoi(v->value); break; } } - if (!content_length) { + if (content_length <= 0) { return NULL; } - buf = ast_alloca(content_length); - if (!fgets(buf, content_length, ser->f)) { + buf = ast_malloc(content_length + 1); + if (!buf) { return NULL; } + res = fread(buf, 1, content_length, ser->f); + if (res < content_length) { + /* Error, distinguishable by ferror() or feof(), but neither + * is good. */ + goto done; + } + buf[content_length] = '\0'; + while ((val = strsep(&buf, "&"))) { var = strsep(&val, "="); if (val) { @@ -654,6 +663,9 @@ struct ast_variable *ast_http_get_post_vars( prev = v; } } + +done: + ast_free(buf); return post_vars; } diff --git a/res/res_jabber.c b/res/res_jabber.c index fa6bbfdbf..fa45fdf6d 100644 --- a/res/res_jabber.c +++ b/res/res_jabber.c @@ -785,7 +785,7 @@ static struct ast_custom_function jabberstatus_function = { */ static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) { - char *aux = NULL, *parse = NULL; + char *parse = NULL; int timeout; int jidlen, resourcelen; struct timeval start; @@ -902,7 +902,7 @@ static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, ch continue; } found = 1; - aux = ast_strdupa(tmp->message); + ast_copy_string(buf, tmp->message, buflen); AST_LIST_REMOVE_CURRENT(list); aji_message_destroy(tmp); break; @@ -927,7 +927,6 @@ static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, ch ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid); return -1; } - ast_copy_string(buf, aux, buflen); return 0; } |