diff -Nru asterisk-1.6.2.5/debian/changelog asterisk-1.6.2.5/debian/changelog --- asterisk-1.6.2.5/debian/changelog 2010-04-14 22:47:49.000000000 +0000 +++ asterisk-1.6.2.5/debian/changelog 2011-07-12 19:49:47.000000000 +0000 @@ -1,3 +1,74 @@ +asterisk (1:1.6.2.5-0ubuntu1.4) lucid-security; urgency=low + + * SECURITY UPDATE: denial of service and possible code exection via + crafted UDPTL packet + - debian/patches/AST-2011-002-1.6.2.diff: properly calculate lengths in + main/udptl.c. + - CVE-2011-1147 + * SECURITY UPDATE: denial of service via manager session with invalid + data + - debian/patches/AST-2011-003-1.6.2.diff: check for errors in + main/manager.c. + - CVE-2011-1174 + * SECURITY UPDATE: denial of service via many short TLS sessions + - debian/patches/AST-2011-004-1.6.2.diff: gracefully handle failures + in main/tcptls.c. + - CVE-2011-1175 + * SECURITY UPDATE: denial of service via a series of TCP connections + - debian/patches/AST-2011-005-1.6.2.diff: add timeouts and session + limits to main/manager.c, configs/manager.conf.sample, + channels/chan_sip.c, channels/chan_skinny.c, main/http.c, + configs/{skinny,sip,http}.conf.sample. + - CVE-2011-1507 + * SECURITY UPDATE: remote command execution via incomplete system + privilege check + - debian/patches/AST-2011-006-1.6.2.diff: correctly check privileges in + main/manager.c. + - CVE-2011-1599 + * SECURITY UPDATE: denial of service via crafted packet and SIP channel + driver + - debian/patches/AST-2011-008.diff: set proper length in + channels/chan_sip.c. + - CVE-2011-2529 + * SECURITY UPDATE: denial of service and possible code execution via + IAX2 channel driver crafted frame + - debian/patches/AST-2011-010-1.6.2.diff: validate options in + channels/chan_iax2.c, main/features.c. + - CVE-2011-2535 + * SECURITY UPDATE: account name enumeration + - debian/patches/AST-2011-011-1.6.2.diff: adjust responses in + channels/chan_sip.c. + - CVE-2011-2536 + + -- Marc Deslauriers Tue, 12 Jul 2011 15:49:26 -0400 + +asterisk (1:1.6.2.5-0ubuntu1.3) lucid-security; urgency=low + + * SECURITY UPDATE: Stack buffer overflow in SIP channel driver. (LP: #705014) + - debian/patches/AST-2011-001-1.6.2: The size of the output buffer passed + to the ast_uri_encode function is now properly respected in main/utils.c. + Patch courtesy of upstream. + - CVE-2011-0495 + + -- Dave Walker (Daviey) Thu, 20 Jan 2011 23:31:55 +0000 + +asterisk (1:1.6.2.5-0ubuntu1.2) lucid-proposed; urgency=low + + * debian/patches/unattended_fix: Fix attended transfer call in 1.2.6.5 + Patch based on Asterisk project's upstream patch (between 1.2.6.5 and + 1.2.6.6 where issue is declared to be fixed see issue 16816 on Asterisk + bug tracker). (LP: #686625) + + -- Lionel Porcheron Mon, 06 Dec 2010 16:56:12 +0100 + +asterisk (1:1.6.2.5-0ubuntu1.1) lucid-proposed; urgency=low + + * debian/patches/dnsmgr-A-SRV-handling: Resolve handling of A and SRV + record changes and problem with multiple A/SRV records returned. + Patch based on Asterisk project's upstream patch. (LP: #605358) + + -- Dave Walker (Daviey) Wed, 14 Jul 2010 11:40:55 +0100 + asterisk (1:1.6.2.5-0ubuntu1) lucid; urgency=low * New upstream bugfix release (1.6.2.5) diff -Nru asterisk-1.6.2.5/debian/control asterisk-1.6.2.5/debian/control --- asterisk-1.6.2.5/debian/control 2010-04-13 20:40:24.000000000 +0000 +++ asterisk-1.6.2.5/debian/control 2011-07-12 19:50:11.000000000 +0000 @@ -1,7 +1,7 @@ Source: asterisk Priority: optional Section: comm -Maintainer: Ubuntu MOTU Developers +Maintainer: Ubuntu Developers XSBC-Original-Maintainer: Debian VoIP Team Build-Depends: quilt, debhelper (>= 6.0.7), diff -Nru asterisk-1.6.2.5/debian/patches/AST-2011-001-1.6.2 asterisk-1.6.2.5/debian/patches/AST-2011-001-1.6.2 --- asterisk-1.6.2.5/debian/patches/AST-2011-001-1.6.2 1970-01-01 00:00:00.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/AST-2011-001-1.6.2 2011-01-21 14:49:19.000000000 +0000 @@ -0,0 +1,52 @@ +Description: Stack buffer overflow in SIP channel driver. + Prevent buffer overflows in ast_uri_encode() +Origin: upstream, http://downloads.asterisk.org/pub/security/AST-2011-001.html +Bug-Ubuntu: https://launchpad.net/bugs/705014 +Bug-Debian: http://bugs.debian.org/610487 +Applied-Upstream: http://svnview.digium.com/svn/asterisk?view=revision&revision=301307 +Last-Update: 2011-01-20 + +--- a/main/utils.c ++++ b/main/utils.c +@@ -385,28 +385,27 @@ + char *reserved = ";/?:@&=+$,# "; /* Reserved chars */ + + const char *ptr = string; /* Start with the string */ +- char *out = NULL; +- char *buf = NULL; ++ char *out = outbuf; + +- ast_copy_string(outbuf, string, buflen); +- +- /* If there's no characters to convert, just go through and don't do anything */ +- while (*ptr) { ++ /* If there's no characters to convert, just go through and copy the string */ ++ while (*ptr && out - outbuf < buflen - 1) { + if ((*ptr < 32) || (doreserved && strchr(reserved, *ptr))) { +- /* Oops, we need to start working here */ +- if (!buf) { +- buf = outbuf; +- out = buf + (ptr - string) ; /* Set output ptr */ ++ if (out - outbuf >= buflen - 3) { ++ break; + } ++ + out += sprintf(out, "%%%02x", (unsigned char) *ptr); +- } else if (buf) { +- *out = *ptr; /* Continue copying the string */ ++ } else { ++ *out = *ptr; /* copy the character */ + out++; +- } ++ } + ptr++; + } +- if (buf) ++ ++ if (buflen) { + *out = '\0'; ++ } ++ + return outbuf; + } + diff -Nru asterisk-1.6.2.5/debian/patches/AST-2011-002-1.6.2.diff asterisk-1.6.2.5/debian/patches/AST-2011-002-1.6.2.diff --- asterisk-1.6.2.5/debian/patches/AST-2011-002-1.6.2.diff 1970-01-01 00:00:00.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/AST-2011-002-1.6.2.diff 2011-07-12 19:47:16.000000000 +0000 @@ -0,0 +1,99 @@ +Description: fix denial of service and possible code exection via crafted UDPTL packet +Origin: upstream, http://downloads.asterisk.org/pub/security/AST-2011-002-1.6.2.diff + +Index: asterisk-1.6.2.5/main/udptl.c +=================================================================== +--- asterisk-1.6.2.5.orig/main/udptl.c 2010-02-02 14:58:14.000000000 -0500 ++++ asterisk-1.6.2.5/main/udptl.c 2011-07-12 15:47:08.269864044 -0400 +@@ -217,38 +217,29 @@ + } + *pvalue = (buf[*len] & 0x3F) << 14; + (*len)++; +- /* Indicate we have a fragment */ ++ /* We have a fragment. Currently we don't process fragments. */ ++ ast_debug(1, "UDPTL packet with length greater than 16K received, decoding will fail\n"); + return 1; + } + /*- End of function --------------------------------------------------------*/ + + static int decode_open_type(uint8_t *buf, unsigned int limit, unsigned int *len, const uint8_t **p_object, unsigned int *p_num_octets) + { +- unsigned int octet_cnt; +- unsigned int octet_idx; +- unsigned int length; +- unsigned int i; +- const uint8_t **pbuf; +- +- for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) { +- octet_cnt = 0; +- if ((length = decode_length(buf, limit, len, &octet_cnt)) < 0) +- return -1; +- if (octet_cnt > 0) { +- *p_num_octets += octet_cnt; +- +- pbuf = &p_object[octet_idx]; +- i = 0; +- /* Make sure the buffer contains at least the number of bits requested */ +- if ((*len + octet_cnt) > limit) +- return -1; ++ unsigned int octet_cnt = 0; + +- *pbuf = &buf[*len]; +- *len += octet_cnt; +- } +- if (length == 0) +- break; ++ if (decode_length(buf, limit, len, &octet_cnt) != 0) ++ return -1; ++ ++ if (octet_cnt > 0) { ++ /* Make sure the buffer contains at least the number of bits requested */ ++ if ((*len + octet_cnt) > limit) ++ return -1; ++ ++ *p_num_octets = octet_cnt; ++ *p_object = &buf[*len]; ++ *len += octet_cnt; + } ++ + return 0; + } + /*- End of function --------------------------------------------------------*/ +@@ -335,8 +326,8 @@ + const uint8_t *data; + unsigned int ifp_len; + int repaired[16]; +- const uint8_t *bufs[16]; +- unsigned int lengths[16]; ++ const uint8_t *bufs[ARRAY_LEN(s->f) - 1]; ++ unsigned int lengths[ARRAY_LEN(s->f) - 1]; + int span; + int entries; + int ifp_no; +@@ -366,13 +357,13 @@ + do { + if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) + return -1; +- for (i = 0; i < count; i++) { ++ for (i = 0; i < count && total_count + i < ARRAY_LEN(bufs); i++) { + if ((stat1 = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) + return -1; + } +- total_count += count; ++ total_count += i; + } +- while (stat2 > 0); ++ while (stat2 > 0 && total_count < ARRAY_LEN(bufs)); + /* Step through in reverse order, so we go oldest to newest */ + for (i = total_count; i > 0; i--) { + if (seq_no - i >= s->rx_seq_no) { +@@ -435,6 +426,9 @@ + if (ptr + 1 > len) + return -1; + entries = buf[ptr++]; ++ if (entries > MAX_FEC_ENTRIES) { ++ return -1; ++ } + s->rx[x].fec_entries = entries; + + /* Decode the elements */ diff -Nru asterisk-1.6.2.5/debian/patches/AST-2011-003-1.6.2.diff asterisk-1.6.2.5/debian/patches/AST-2011-003-1.6.2.diff --- asterisk-1.6.2.5/debian/patches/AST-2011-003-1.6.2.diff 1970-01-01 00:00:00.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/AST-2011-003-1.6.2.diff 2011-07-12 19:47:28.000000000 +0000 @@ -0,0 +1,44 @@ +Description: fix denial of service via manager session with invalid data +Origin: upstream, http://downloads.asterisk.org/pub/security/AST-2011-003-1.6.2.diff + +Index: asterisk-1.6.2.5/main/manager.c +=================================================================== +--- asterisk-1.6.2.5.orig/main/manager.c 2009-12-02 17:05:11.000000000 -0500 ++++ asterisk-1.6.2.5/main/manager.c 2011-07-12 15:47:24.919864042 -0400 +@@ -219,6 +219,7 @@ + struct mansession_session *session; + FILE *f; + int fd; ++ int write_error:1; + }; + + #define NEW_EVENT(m) (AST_LIST_NEXT(m->session->last_ev, eq_next)) +@@ -943,11 +944,15 @@ + */ + static int send_string(struct mansession *s, char *string) + { +- if (s->f) { +- return ast_careful_fwrite(s->f, s->fd, string, strlen(string), s->session->writetimeout); +- } else { +- return ast_careful_fwrite(s->session->f, s->session->fd, string, strlen(string), s->session->writetimeout); ++ int res; ++ FILE *f = s->f ? s->f : s->session->f; ++ int fd = s->f ? s->fd : s->session->fd; ++ ++ if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) { ++ s->write_error = 1; + } ++ ++ return res; + } + + /*! +@@ -3200,7 +3205,7 @@ + + astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */ + for (;;) { +- if ((res = do_message(&s)) < 0) ++ if ((res = do_message(&s)) < 0 || s.write_error) + break; + } + /* session is over, explain why and terminate */ diff -Nru asterisk-1.6.2.5/debian/patches/AST-2011-004-1.6.2.diff asterisk-1.6.2.5/debian/patches/AST-2011-004-1.6.2.diff --- asterisk-1.6.2.5/debian/patches/AST-2011-004-1.6.2.diff 1970-01-01 00:00:00.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/AST-2011-004-1.6.2.diff 2011-07-12 19:47:35.000000000 +0000 @@ -0,0 +1,22 @@ +Description: fix denial of service via many short TLS sessions +Origin: upstream, http://downloads.asterisk.org/pub/security/AST-2011-004-1.6.2.diff + +Index: asterisk-1.6.2.5/main/tcptls.c +=================================================================== +--- asterisk-1.6.2.5.orig/main/tcptls.c 2009-10-22 17:55:48.000000000 -0400 ++++ asterisk-1.6.2.5/main/tcptls.c 2011-07-12 15:47:33.449864039 -0400 +@@ -138,8 +138,12 @@ + * open a FILE * as appropriate. + */ + if (!tcptls_session->parent->tls_cfg) { +- tcptls_session->f = fdopen(tcptls_session->fd, "w+"); +- setvbuf(tcptls_session->f, NULL, _IONBF, 0); ++ if ((tcptls_session->f = fdopen(tcptls_session->fd, "w+"))) { ++ if(setvbuf(tcptls_session->f, NULL, _IONBF, 0)) { ++ fclose(tcptls_session->f); ++ tcptls_session->f = NULL; ++ } ++ } + } + #ifdef DO_SSL + else if ( (tcptls_session->ssl = SSL_new(tcptls_session->parent->tls_cfg->ssl_ctx)) ) { diff -Nru asterisk-1.6.2.5/debian/patches/AST-2011-005-1.6.2.diff asterisk-1.6.2.5/debian/patches/AST-2011-005-1.6.2.diff --- asterisk-1.6.2.5/debian/patches/AST-2011-005-1.6.2.diff 1970-01-01 00:00:00.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/AST-2011-005-1.6.2.diff 2011-07-12 19:48:30.000000000 +0000 @@ -0,0 +1,766 @@ +Description: fix denial of service via a series of TCP connections +Origin: backport, http://downloads.asterisk.org/pub/security/AST-2011-005-1.6.2.diff + +Index: asterisk-1.6.2.5/main/manager.c +=================================================================== +--- asterisk-1.6.2.5.orig/main/manager.c 2011-07-12 15:47:24.000000000 -0400 ++++ asterisk-1.6.2.5/main/manager.c 2011-07-12 15:48:22.079864027 -0400 +@@ -119,15 +119,21 @@ + + static AST_LIST_HEAD_STATIC(all_events, eventqent); + ++static const int DEFAULT_AUTHTIMEOUT = 30; /*!< Default setting for authtimeout */ ++static const int DEFAULT_AUTHLIMIT = 50; /*!< Default setting for authlimit */ ++ + static int displayconnects = 1; + static int allowmultiplelogin = 1; + static int timestampevents; + static int httptimeout = 60; + static int manager_enabled = 0; + static int webmanager_enabled = 0; ++static int authtimeout; ++static int authlimit; + + static int block_sockets; + static int num_sessions; ++static int unauth_sessions = 0; + + static int manager_debug; /*!< enable some debugging code in the manager */ + +@@ -205,6 +211,7 @@ + int send_events; /*!< XXX what ? */ + struct eventqent *last_ev; /*!< last event processed. */ + int writetimeout; /*!< Timeout for ast_carefulwrite() */ ++ time_t authstart; + int pending_event; /*!< Pending events indicator in case when waiting_thread is NULL */ + AST_LIST_HEAD_NOLOCK(mansession_datastores, ast_datastore) datastores; /*!< Data stores on the session */ + AST_LIST_ENTRY(mansession_session) list; +@@ -1750,6 +1757,7 @@ + return -1; + } + s->session->authenticated = 1; ++ ast_atomic_fetchadd_int(&unauth_sessions, -1); + if (manager_displayconnects(s->session)) + ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr)); + ast_log(LOG_EVENT, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr)); +@@ -3067,6 +3075,8 @@ + int res, x; + int maxlen = sizeof(s->session->inbuf) - 1; + char *src = s->session->inbuf; ++ int timeout = -1; ++ time_t now; + + /* + * Look for \r\n within the buffer. If found, copy to the output +@@ -3094,6 +3104,20 @@ + } + res = 0; + while (res == 0) { ++ /* calculate a timeout if we are not authenticated */ ++ if (!s->session->authenticated) { ++ if(time(&now) == -1) { ++ ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); ++ return -1; ++ } ++ ++ timeout = (authtimeout - (now - s->session->authstart)) * 1000; ++ if (timeout < 0) { ++ /* we have timed out */ ++ return 0; ++ } ++ } ++ + /* XXX do we really need this locking ? */ + ast_mutex_lock(&s->session->__lock); + if (s->session->pending_event) { +@@ -3104,7 +3128,7 @@ + s->session->waiting_thread = pthread_self(); + ast_mutex_unlock(&s->session->__lock); + +- res = ast_wait_for_input(s->session->fd, -1); /* return 0 on timeout ? */ ++ res = ast_wait_for_input(s->session->fd, timeout); + + ast_mutex_lock(&s->session->__lock); + s->session->waiting_thread = AST_PTHREADT_NULL; +@@ -3137,6 +3161,7 @@ + struct message m = { 0 }; + char header_buf[sizeof(s->session->inbuf)] = { '\0' }; + int res; ++ time_t now; + + for (;;) { + /* Check if any events are pending and do them if needed */ +@@ -3144,6 +3169,17 @@ + return -1; + res = get_input(s, header_buf); + if (res == 0) { ++ if (!s->session->authenticated) { ++ if(time(&now) == -1) { ++ ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); ++ return -1; ++ } ++ ++ if (now - s->session->authstart > authtimeout) { ++ ast_log(LOG_EVENT, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout); ++ return -1; ++ } ++ } + continue; + } else if (res > 0) { + if (ast_strlen_zero(header_buf)) +@@ -3167,13 +3203,22 @@ + static void *session_do(void *data) + { + struct ast_tcptls_session_instance *ser = data; +- struct mansession_session *session = ast_calloc(1, sizeof(*session)); ++ struct mansession_session *session = NULL; + struct mansession s = {.session = NULL, }; + int flags; + int res; + +- if (session == NULL) ++ if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) { ++ fclose(ser->f); ++ ast_atomic_fetchadd_int(&unauth_sessions, -1); ++ goto done; ++ } ++ ++ if ((session = ast_calloc(1, sizeof(*session))) == NULL) { ++ fclose(ser->f); ++ ast_atomic_fetchadd_int(&unauth_sessions, -1); + goto done; ++ } + + session->writetimeout = 100; + session->waiting_thread = AST_PTHREADT_NULL; +@@ -3203,6 +3248,13 @@ + ast_atomic_fetchadd_int(&num_sessions, 1); + AST_LIST_UNLOCK(&sessions); + ++ if(time(&session->authstart) == -1) { ++ ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno)); ++ ast_atomic_fetchadd_int(&unauth_sessions, -1); ++ destroy_session(session); ++ goto done; ++ } ++ + astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */ + for (;;) { + if ((res = do_message(&s)) < 0 || s.write_error) +@@ -3214,6 +3266,7 @@ + ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); + ast_log(LOG_EVENT, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); + } else { ++ ast_atomic_fetchadd_int(&unauth_sessions, -1); + if (displayconnects) + ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); + ast_log(LOG_EVENT, "Failed attempt from %s\n", ast_inet_ntoa(session->sin.sin_addr)); +@@ -4112,6 +4165,8 @@ + return 0; + + displayconnects = 1; ++ authtimeout = DEFAULT_AUTHTIMEOUT; ++ authlimit = DEFAULT_AUTHLIMIT; + if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) { + ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf, or configuration is invalid. Asterisk management interface (AMI) disabled.\n"); + return 0; +@@ -4173,6 +4228,22 @@ + manager_debug = ast_true(val); + } else if (!strcasecmp(var->name, "httptimeout")) { + newhttptimeout = atoi(val); ++ } else if (!strcasecmp(var->name, "authtimeout")) { ++ int timeout = atoi(var->value); ++ ++ if (timeout < 1) { ++ ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", var->value); ++ } else { ++ authtimeout = timeout; ++ } ++ } else if (!strcasecmp(var->name, "authlimit")) { ++ int limit = atoi(var->value); ++ ++ if (limit < 1) { ++ ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", var->value); ++ } else { ++ authlimit = limit; ++ } + } else { + ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n", + var->name, val); +Index: asterisk-1.6.2.5/configs/manager.conf.sample +=================================================================== +--- asterisk-1.6.2.5.orig/configs/manager.conf.sample 2008-07-21 17:12:51.000000000 -0400 ++++ asterisk-1.6.2.5/configs/manager.conf.sample 2011-07-12 15:47:56.069864034 -0400 +@@ -25,6 +25,17 @@ + ;webenabled = yes + port = 5038 + ++; authtimeout specifies the maximum number of seconds a client has to ++; authenticate. If the client does not authenticate beofre this timeout ++; expires, the client will be disconnected. (default: 30 seconds) ++ ++;authtimeout = 30 ++ ++; authlimit specifies the maximum number of unauthenticated sessions that will ++; be allowed to connect at any given time. ++ ++;authlimit = 50 ++ + ;httptimeout = 60 + ; a) httptimeout sets the Max-Age of the http cookie + ; b) httptimeout is the amount of time the webserver waits +Index: asterisk-1.6.2.5/channels/chan_sip.c +=================================================================== +--- asterisk-1.6.2.5.orig/channels/chan_sip.c 2010-02-02 14:58:14.000000000 -0500 ++++ asterisk-1.6.2.5/channels/chan_sip.c 2011-07-12 15:47:56.079864034 -0400 +@@ -500,6 +500,8 @@ + #define DEFAULT_MWI_EXPIRY 3600 + #define DEFAULT_REGISTRATION_TIMEOUT 20 + #define DEFAULT_MAX_FORWARDS "70" ++#define DEFAULT_AUTHLIMIT 100 ++#define DEFAULT_AUTHTIMEOUT 30 + + /* guard limit must be larger than guard secs */ + /* guard min must be < 1000, and should be >= 250 */ +@@ -552,6 +554,10 @@ + + #define SDP_MAX_RTPMAP_CODECS 32 /*!< Maximum number of codecs allowed in received SDP */ + ++static int unauth_sessions = 0; ++static int authlimit = DEFAULT_AUTHLIMIT; ++static int authtimeout = DEFAULT_AUTHTIMEOUT; ++ + /*! \brief Global jitterbuffer configuration - by default, jb is disabled */ + static struct ast_jb_conf default_jbconf = + { +@@ -1211,6 +1217,7 @@ + char debug; /*!< print extra debugging if non zero */ + char has_to_tag; /*!< non-zero if packet has To: tag */ + char ignore; /*!< if non-zero This is a re-transmit, ignore it */ ++ char authenticated; /*!< non-zero if this request was authenticated */ + /* Array of offsets into the request string of each SIP header*/ + ptrdiff_t header[SIP_MAX_HEADERS]; + /* Array of offsets into the request string of each SDP line*/ +@@ -2903,21 +2910,48 @@ + return _sip_tcp_helper_thread(NULL, tcptls_session); + } + ++/*! \brief Check if the authtimeout has expired. ++ * \param start the time when the session started ++ * ++ * \retval 0 the timeout has expired ++ * \retval -1 error ++ * \return the number of milliseconds until the timeout will expire ++ */ ++static int sip_check_authtimeout(time_t start) ++{ ++ int timeout; ++ time_t now; ++ if(time(&now) == -1) { ++ ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); ++ return -1; ++ } ++ ++ timeout = (authtimeout - (now - start)) * 1000; ++ if (timeout < 0) { ++ /* we have timed out */ ++ return 0; ++ } ++ ++ return timeout; ++} ++ + /*! \brief SIP TCP thread management function + This function reads from the socket, parses the packet into a request + */ + static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *tcptls_session) + { +- int res, cl; ++ int res, cl, timeout = -1, authenticated = 0, flags; ++ time_t start; + struct sip_request req = { 0, } , reqcpy = { 0, }; + struct sip_threadinfo *me = NULL; + char buf[1024] = ""; + struct pollfd fds[2] = { { 0 }, { 0 }, }; + struct ast_tcptls_session_args *ca = NULL; + +- /* If this is a server session, then the connection has already been setup, +- * simply create the threadinfo object so we can access this thread for writing. +- * ++ /* If this is a server session, then the connection has already been ++ * setup. Check if the authlimit has been reached and if not create the ++ * threadinfo object so we can access this thread for writing. ++ * + * if this is a client connection more work must be done. + * 1. We own the parent session args for a client connection. This pointer needs + * to be held on to so we can decrement it's ref count on thread destruction. +@@ -2926,6 +2960,22 @@ + * 3. Last, the tcptls_session must be started. + */ + if (!tcptls_session->client) { ++ if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) { ++ /* unauth_sessions is decremented in the cleanup code */ ++ goto cleanup; ++ } ++ ++ if ((flags = fcntl(tcptls_session->fd, F_GETFL)) == -1) { ++ ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno)); ++ goto cleanup; ++ } ++ ++ flags |= O_NONBLOCK; ++ if (fcntl(tcptls_session->fd, F_SETFL, flags) == -1) { ++ ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno)); ++ goto cleanup; ++ } ++ + if (!(me = sip_threadinfo_create(tcptls_session, tcptls_session->ssl ? SIP_TRANSPORT_TLS : SIP_TRANSPORT_TCP))) { + goto cleanup; + } +@@ -2955,14 +3005,41 @@ + if (!(reqcpy.data = ast_str_create(SIP_MIN_PACKET))) + goto cleanup; + ++ if(time(&start) == -1) { ++ ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); ++ goto cleanup; ++ } ++ + for (;;) { + struct ast_str *str_save; + +- res = ast_poll(fds, 2, -1); /* polls for both socket and alert_pipe */ ++ if (!tcptls_session->client && req.authenticated && !authenticated) { ++ authenticated = 1; ++ ast_atomic_fetchadd_int(&unauth_sessions, -1); ++ } ++ ++ /* calculate the timeout for unauthenticated server sessions */ ++ if (!tcptls_session->client && !authenticated ) { ++ if ((timeout = sip_check_authtimeout(start)) < 0) { ++ goto cleanup; ++ } ++ ++ if (timeout == 0) { ++ ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); ++ goto cleanup; ++ } ++ } else { ++ timeout = -1; ++ } + ++ 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); + goto cleanup; ++ } else if (res == 0) { ++ /* timeout */ ++ ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); ++ goto cleanup; + } + + /* handle the socket event, check for both reads from the socket fd, +@@ -2995,6 +3072,29 @@ + + /* Read in headers one line at a time */ + while (req.len < 4 || strncmp(REQ_OFFSET_TO_STR(&req, len - 4), "\r\n\r\n", 4)) { ++ if (!tcptls_session->client && !authenticated ) { ++ if ((timeout = sip_check_authtimeout(start)) < 0) { ++ goto cleanup; ++ } ++ ++ if (timeout == 0) { ++ ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); ++ goto cleanup; ++ } ++ } else { ++ timeout = -1; ++ } ++ ++ res = ast_wait_for_input(tcptls_session->fd, timeout); ++ if (res < 0) { ++ ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res); ++ goto cleanup; ++ } else if (res == 0) { ++ /* timeout */ ++ ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); ++ goto cleanup; ++ } ++ + ast_mutex_lock(&tcptls_session->lock); + if (!fgets(buf, sizeof(buf), tcptls_session->f)) { + ast_mutex_unlock(&tcptls_session->lock); +@@ -3012,6 +3112,29 @@ + if (sscanf(get_header(&reqcpy, "Content-Length"), "%30d", &cl)) { + while (cl > 0) { + size_t bytes_read; ++ if (!tcptls_session->client && !authenticated ) { ++ if ((timeout = sip_check_authtimeout(start)) < 0) { ++ goto cleanup; ++ } ++ ++ if (timeout == 0) { ++ ast_debug(2, "SIP %s server timed out", tcptls_session->ssl ? "SSL": "TCP"); ++ goto cleanup; ++ } ++ } else { ++ timeout = -1; ++ } ++ ++ res = ast_wait_for_input(tcptls_session->fd, timeout); ++ if (res < 0) { ++ ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res); ++ goto cleanup; ++ } else if (res == 0) { ++ /* timeout */ ++ ast_debug(2, "SIP %s server timed out", tcptls_session->ssl ? "SSL": "TCP"); ++ goto cleanup; ++ } ++ + ast_mutex_lock(&tcptls_session->lock); + if (!(bytes_read = fread(buf, 1, MIN(sizeof(buf) - 1, cl), tcptls_session->f))) { + ast_mutex_unlock(&tcptls_session->lock); +@@ -3069,6 +3192,10 @@ + ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); + + cleanup: ++ if (!tcptls_session->client && !authenticated) { ++ ast_atomic_fetchadd_int(&unauth_sessions, -1); ++ } ++ + if (me) { + ao2_t_unlink(threadt, me, "Removing tcptls helper thread, thread is closing"); + ao2_t_ref(me, -1, "Removing tcp_helper_threads threadinfo ref"); +@@ -19973,6 +20100,8 @@ + set_t38_capabilities(p); + } + ++ req->authenticated = 1; ++ + /* We have a succesful authentication, process the SDP portion if there is one */ + if (find_sdp(req)) { + if (process_sdp(p, req, SDP_T38_INITIATE)) { +@@ -21501,8 +21630,10 @@ + get_header(req, "To"), ast_inet_ntoa(sin->sin_addr), + reason); + append_history(p, "RegRequest", "Failed : Account %s : %s", get_header(req, "To"), reason); +- } else ++ } else { ++ req->authenticated = 1; + append_history(p, "RegRequest", "Succeeded : Account %s", get_header(req, "To")); ++ } + + if (res < 1) { + /* Destroy the session, but keep us around for just a bit in case they don't +@@ -21940,6 +22071,11 @@ + } + p->recv = *sin; + ++ /* if we have an owner, then this request has been authenticated */ ++ if (p->owner) { ++ req->authenticated = 1; ++ } ++ + if (p->do_history) /* This is a request or response, note what it was for */ + append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), REQ_OFFSET_TO_STR(req, rlPart2)); + +@@ -24426,6 +24562,8 @@ + global_qualifyfreq = DEFAULT_QUALIFYFREQ; + global_t38_maxdatagram = -1; + global_shrinkcallerid = 1; ++ authlimit = DEFAULT_AUTHLIMIT; ++ authtimeout = DEFAULT_AUTHTIMEOUT; + + sip_cfg.matchexterniplocally = DEFAULT_MATCHEXTERNIPLOCALLY; + +@@ -24672,6 +24810,18 @@ + mwi_expiry = atoi(v->value); + if (mwi_expiry < 1) + mwi_expiry = DEFAULT_MWI_EXPIRY; ++ } else if (!strcasecmp(v->name, "tcpauthtimeout")) { ++ if (ast_parse_arg(v->value, PARSE_INT32|PARSE_DEFAULT|PARSE_IN_RANGE, ++ &authtimeout, DEFAULT_AUTHTIMEOUT, 1, INT_MAX)) { ++ ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", ++ v->name, v->value, v->lineno, config); ++ } ++ } else if (!strcasecmp(v->name, "tcpauthlimit")) { ++ if (ast_parse_arg(v->value, PARSE_INT32|PARSE_DEFAULT|PARSE_IN_RANGE, ++ &authlimit, DEFAULT_AUTHLIMIT, 1, INT_MAX)) { ++ ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", ++ v->name, v->value, v->lineno, config); ++ } + } else if (!strcasecmp(v->name, "sipdebug")) { + if (ast_true(v->value)) + sipdebug |= sip_debug_config; +Index: asterisk-1.6.2.5/channels/chan_skinny.c +=================================================================== +--- asterisk-1.6.2.5.orig/channels/chan_skinny.c 2009-09-02 17:37:53.000000000 -0400 ++++ asterisk-1.6.2.5/channels/chan_skinny.c 2011-07-12 15:47:56.079864034 -0400 +@@ -100,6 +100,8 @@ + #define DEFAULT_SKINNY_PORT 2000 + #define DEFAULT_SKINNY_BACKLOG 2 + #define SKINNY_MAX_PACKET 1000 ++#define DEFAULT_AUTH_TIMEOUT 30 ++#define DEFAULT_AUTH_LIMIT 50 + + static struct { + unsigned int tos; +@@ -111,6 +113,9 @@ + } qos = { 0, 0, 0, 0, 0, 0 }; + + static int keep_alive = 120; ++static int auth_timeout = DEFAULT_AUTH_TIMEOUT; ++static int auth_limit = DEFAULT_AUTH_LIMIT; ++static int unauth_sessions = 0; + static char global_vmexten[AST_MAX_EXTENSION]; /* Voicemail pilot number */ + static char used_context[AST_MAX_EXTENSION]; /* placeholder to check if context are already used in regcontext */ + static char regcontext[AST_MAX_CONTEXT]; /* Context for auto-extension */ +@@ -1306,6 +1311,7 @@ + struct skinnysession { + pthread_t t; + ast_mutex_t lock; ++ time_t start; + struct sockaddr_in sin; + int fd; + char inbuf[SKINNY_MAX_PACKET]; +@@ -4554,6 +4560,8 @@ + + return 0; + } ++ ast_atomic_fetchadd_int(&unauth_sessions, -1); ++ + ast_verb(3, "Device '%s' successfully registered\n", name); + + d = s->device; +@@ -6232,6 +6240,9 @@ + if (s->fd > -1) + close(s->fd); + ++ if (!s->device) ++ ast_atomic_fetchadd_int(&unauth_sessions, -1); ++ + ast_mutex_destroy(&s->lock); + + ast_free(s); +@@ -6247,13 +6258,30 @@ + { + int res; + int dlen = 0; ++ int timeout = keep_alive * 1100; ++ time_t now; + int *bufaddr; + struct pollfd fds[1]; + ++ if (!s->device) { ++ if(time(&now) == -1) { ++ ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); ++ return -1; ++ } ++ ++ timeout = (auth_timeout - (now - s->start)) * 1000; ++ if (timeout < 0) { ++ /* we have timed out */ ++ if (skinnydebug) ++ ast_verb(1, "Skinny Client failed to authenticate in %d seconds\n", auth_timeout); ++ return -1; ++ } ++ } ++ + fds[0].fd = s->fd; + fds[0].events = POLLIN; + fds[0].revents = 0; +- res = ast_poll(fds, 1, (keep_alive * 1100)); /* If nothing has happen, client is dead */ ++ res = ast_poll(fds, 1, timeout); /* If nothing has happen, client is dead */ + /* we add 10% to the keep_alive to deal */ + /* with network delays, etc */ + if (res < 0) { +@@ -6262,8 +6290,13 @@ + return res; + } + } else if (res == 0) { +- if (skinnydebug) +- ast_verb(1, "Skinny Client was lost, unregistering\n"); ++ if (skinnydebug) { ++ if (s->device) { ++ ast_verb(1, "Skinny Client was lost, unregistering\n"); ++ } else { ++ ast_verb(1, "Skinny Client failed to authenticate in %d seconds\n", auth_timeout); ++ } ++ } + skinny_unregister(NULL, s); + return -1; + } +@@ -6396,18 +6429,35 @@ + ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno)); + continue; + } ++ ++ if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= auth_limit) { ++ close(as); ++ ast_atomic_fetchadd_int(&unauth_sessions, -1); ++ continue; ++ } ++ + p = getprotobyname("tcp"); + if(p) { + if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) { + ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno)); + } + } +- if (!(s = ast_calloc(1, sizeof(struct skinnysession)))) ++ if (!(s = ast_calloc(1, sizeof(struct skinnysession)))) { ++ close(as); ++ ast_atomic_fetchadd_int(&unauth_sessions, -1); + continue; ++ } + + memcpy(&s->sin, &sin, sizeof(sin)); + ast_mutex_init(&s->lock); + s->fd = as; ++ ++ if(time(&s->start) == -1) { ++ ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno)); ++ destroy_session(s); ++ continue; ++ } ++ + AST_LIST_LOCK(&sessions); + AST_LIST_INSERT_HEAD(&sessions, s, list); + AST_LIST_UNLOCK(&sessions); +@@ -6561,6 +6611,26 @@ + } else if (!strcasecmp(v->name, "keepalive")) { + keep_alive = atoi(v->value); + continue; ++ } else if (!strcasecmp(v->name, "authtimeout")) { ++ int timeout = atoi(v->value); ++ ++ if (timeout < 1) { ++ ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", v->value); ++ auth_timeout = DEFAULT_AUTH_TIMEOUT; ++ } else { ++ auth_timeout = timeout; ++ } ++ continue; ++ } else if (!strcasecmp(v->name, "authlimit")) { ++ int limit = atoi(v->value); ++ ++ if (limit < 1) { ++ ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", v->value); ++ auth_limit = DEFAULT_AUTH_LIMIT; ++ } else { ++ auth_limit = limit; ++ } ++ continue; + } else if (!strcasecmp(v->name, "regcontext")) { + ast_copy_string(newcontexts, v->value, sizeof(newcontexts)); + stringp = newcontexts; +Index: asterisk-1.6.2.5/main/http.c +=================================================================== +--- asterisk-1.6.2.5.orig/main/http.c 2009-08-10 15:36:38.000000000 -0400 ++++ asterisk-1.6.2.5/main/http.c 2011-07-12 15:47:56.079864034 -0400 +@@ -53,12 +53,16 @@ + #include "asterisk/astobj2.h" + + #define MAX_PREFIX 80 ++#define DEFAULT_SESSION_LIMIT 100 + + /* See http.h for more information about the SSL implementation */ + #if defined(HAVE_OPENSSL) && (defined(HAVE_FUNOPEN) || defined(HAVE_FOPENCOOKIE)) + #define DO_SSL /* comment in/out if you want to support ssl */ + #endif + ++static int session_limit = DEFAULT_SESSION_LIMIT; ++static int session_count = 0; ++ + static struct ast_tls_config http_tls_cfg; + + static void *httpd_helper_thread(void *arg); +@@ -668,6 +672,10 @@ + unsigned int static_content = 0; + struct ast_variable *tail = headers; + ++ if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) { ++ goto done; ++ } ++ + if (!fgets(buf, sizeof(buf), ser->f)) { + goto done; + } +@@ -778,6 +786,7 @@ + } + + done: ++ ast_atomic_fetchadd_int(&session_count, -1); + fclose(ser->f); + ao2_ref(ser, -1); + ser = NULL; +@@ -927,6 +936,12 @@ + } + } else if (!strcasecmp(v->name, "redirect")) { + add_redirect(v->value); ++ } else if (!strcasecmp(v->name, "sessionlimit")) { ++ if (ast_parse_arg(v->value, PARSE_INT32|PARSE_DEFAULT|PARSE_IN_RANGE, ++ &session_limit, DEFAULT_SESSION_LIMIT, 1, INT_MAX)) { ++ ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n", ++ v->name, v->value, v->lineno); ++ } + } else { + ast_log(LOG_WARNING, "Ignoring unknown option '%s' in http.conf\n", v->name); + } +Index: asterisk-1.6.2.5/configs/skinny.conf.sample +=================================================================== +--- asterisk-1.6.2.5.orig/configs/skinny.conf.sample 2009-08-03 16:58:48.000000000 -0400 ++++ asterisk-1.6.2.5/configs/skinny.conf.sample 2011-07-12 15:47:56.079864034 -0400 +@@ -9,6 +9,15 @@ + ; Use M for month, D for day, Y for year, A for 12-hour time. + keepalive=120 + ++;authtimeout = 30 ; authtimeout specifies the maximum number of seconds a ++ ; client has to authenticate. If the client does not ++ ; authenticate beofre this timeout expires, the client ++ ; will be disconnected. (default: 30 seconds) ++ ++;authlimit = 50 ; authlimit specifies the maximum number of ++ ; unauthenticated sessions that will be allowed to ++ ; connect at any given time. (default: 50) ++ + ;vmexten=8500 ; Systemwide voicemailmain pilot number + ; It must be in the same context as the calling + ; device/line +Index: asterisk-1.6.2.5/configs/sip.conf.sample +=================================================================== +--- asterisk-1.6.2.5.orig/configs/sip.conf.sample 2010-01-07 04:49:54.000000000 -0500 ++++ asterisk-1.6.2.5/configs/sip.conf.sample 2011-07-12 15:47:56.079864034 -0400 +@@ -141,6 +141,16 @@ + ; A list of valid SSL cipher strings can be found at: + ; http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS + ++;tcpauthtimeout = 30 ; tcpauthtimeout specifies the maximum number ++ ; of seconds a client has to authenticate. If ++ ; the client does not authenticate beofre this ++ ; timeout expires, the client will be ++ ; disconnected. (default: 30 seconds) ++ ++;tcpauthlimit = 100 ; tcpauthlimit specifies the maximum number of ++ ; unauthenticated sessions that will be allowed ++ ; to connect at any given time. (default: 100) ++ + srvlookup=yes ; Enable DNS SRV lookups on outbound calls + ; Note: Asterisk only uses the first host + ; in SRV records +Index: asterisk-1.6.2.5/configs/http.conf.sample +=================================================================== +--- asterisk-1.6.2.5.orig/configs/http.conf.sample 2008-06-25 21:11:43.000000000 -0400 ++++ asterisk-1.6.2.5/configs/http.conf.sample 2011-07-12 15:47:56.079864034 -0400 +@@ -32,6 +32,11 @@ + ; + ;prefix=asterisk + ; ++; sessionlimit specifies the maximum number of httpsessions that will be ++; allowed to exist at any given time. (default: 100) ++; ++;sessionlimit=100 ++; + ; Whether Asterisk should serve static content from http-static + ; Default is no. + ; diff -Nru asterisk-1.6.2.5/debian/patches/AST-2011-006-1.6.2.diff asterisk-1.6.2.5/debian/patches/AST-2011-006-1.6.2.diff --- asterisk-1.6.2.5/debian/patches/AST-2011-006-1.6.2.diff 1970-01-01 00:00:00.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/AST-2011-006-1.6.2.diff 2011-07-12 19:48:40.000000000 +0000 @@ -0,0 +1,55 @@ +Description: fix remote command execution via incomplete system privilege check +Origin: backport, http://downloads.asterisk.org/pub/security/AST-2011-006-1.6.2.diff + +Index: asterisk-1.6.2.5/main/manager.c +=================================================================== +--- asterisk-1.6.2.5.orig/main/manager.c 2011-07-12 15:48:22.079864027 -0400 ++++ asterisk-1.6.2.5/main/manager.c 2011-07-12 15:48:37.639864022 -0400 +@@ -2458,6 +2458,25 @@ + format = 0; + ast_parse_allow_disallow(NULL, &format, codecs, 1); + } ++ if (!ast_strlen_zero(app)) { ++ /* To run the System application (or anything else that goes to ++ * shell), you must have the additional System privilege */ ++ if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) ++ && ( ++ strcasestr(app, "system") || /* System(rm -rf /) ++ TrySystem(rm -rf /) */ ++ strcasestr(app, "exec") || /* Exec(System(rm -rf /)) ++ TryExec(System(rm -rf /)) */ ++ strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /) ++ EAGI(/bin/rm,-rf /) */ ++ strstr(appdata, "SHELL") || /* NoOp(${SHELL(rm -rf /)}) */ ++ strstr(appdata, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ ++ )) { ++ astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have."); ++ return 0; ++ } ++ } ++ + if (ast_true(async)) { + struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast)); + if (!fast) { +@@ -2488,21 +2507,6 @@ + } + } + } else if (!ast_strlen_zero(app)) { +- /* To run the System application (or anything else that goes to shell), you must have the additional System privilege */ +- if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) +- && ( +- strcasestr(app, "system") == 0 || /* System(rm -rf /) +- TrySystem(rm -rf /) */ +- strcasestr(app, "exec") || /* Exec(System(rm -rf /)) +- TryExec(System(rm -rf /)) */ +- strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /) +- EAGI(/bin/rm,-rf /) */ +- strstr(appdata, "SHELL") || /* NoOp(${SHELL(rm -rf /)}) */ +- strstr(appdata, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ +- )) { +- astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have."); +- return 0; +- } + res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL); + } else { + if (exten && context && pi) diff -Nru asterisk-1.6.2.5/debian/patches/AST-2011-008.diff asterisk-1.6.2.5/debian/patches/AST-2011-008.diff --- asterisk-1.6.2.5/debian/patches/AST-2011-008.diff 1970-01-01 00:00:00.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/AST-2011-008.diff 2011-07-12 19:48:49.000000000 +0000 @@ -0,0 +1,17 @@ +Description: fix denial of service via crafted packet and SIP channel driver +Origin: upstream, http://downloads.asterisk.org/pub/security/AST-2011-008.diff + +Index: asterisk-1.6.2.5/channels/chan_sip.c +=================================================================== +--- asterisk-1.6.2.5.orig/channels/chan_sip.c 2011-07-12 15:47:56.079864034 -0400 ++++ asterisk-1.6.2.5/channels/chan_sip.c 2011-07-12 15:48:46.949864020 -0400 +@@ -21992,7 +21992,8 @@ + return -1; + } + +- req.len = res; ++ /* req.data will have the correct length in case of nulls */ ++ req.len = ast_str_strlen(req.data); + req.socket.fd = sipsock; + set_socket_transport(&req.socket, SIP_TRANSPORT_UDP); + req.socket.tcptls_session = NULL; diff -Nru asterisk-1.6.2.5/debian/patches/AST-2011-010-1.6.2.diff asterisk-1.6.2.5/debian/patches/AST-2011-010-1.6.2.diff --- asterisk-1.6.2.5/debian/patches/AST-2011-010-1.6.2.diff 1970-01-01 00:00:00.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/AST-2011-010-1.6.2.diff 2011-07-12 19:49:00.000000000 +0000 @@ -0,0 +1,63 @@ +Description: fix denial of service and possible code execution via IAX2 channel driver crafted frame +Origin: upstream, http://downloads.asterisk.org/pub/security/AST-2011-010-1.6.2.diff + +Index: asterisk-1.6.2.5/channels/chan_iax2.c +=================================================================== +--- asterisk-1.6.2.5.orig/channels/chan_iax2.c 2010-01-07 15:17:48.000000000 -0500 ++++ asterisk-1.6.2.5/channels/chan_iax2.c 2011-07-12 15:48:56.879864018 -0400 +@@ -5049,7 +5049,14 @@ + case AST_OPTION_OPRMODE: + errno = EINVAL; + return -1; +- default: ++ /* These options are sent to the other side across the network where ++ * they will be passed to whatever channel is bridged there. Don't ++ * do anything silly like pass an option that transmits pointers to ++ * memory on this machine to a remote machine to use */ ++ case AST_OPTION_TONE_VERIFY: ++ case AST_OPTION_TDD: ++ case AST_OPTION_RELAXDTMF: ++ case AST_OPTION_AUDIO_MODE: + { + unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); + struct chan_iax2_pvt *pvt; +@@ -5077,7 +5084,12 @@ + ast_free(h); + return res; + } ++ default: ++ return -1; + } ++ ++ /* Just in case someone does a break instead of a return */ ++ return -1; + } + + static struct ast_frame *iax2_read(struct ast_channel *c) +Index: asterisk-1.6.2.5/main/features.c +=================================================================== +--- asterisk-1.6.2.5.orig/main/features.c 2010-01-06 14:09:08.000000000 -0500 ++++ asterisk-1.6.2.5/main/features.c 2011-07-12 15:48:56.889864018 -0400 +@@ -2683,10 +2683,19 @@ + break; + case AST_CONTROL_OPTION: + aoh = f->data.ptr; +- /* Forward option Requests */ ++ /* Forward option Requests, but only ones we know are safe ++ * These are ONLY sent by chan_iax2 and I'm not convinced that ++ * they are useful. I haven't deleted them entirely because I ++ * just am not sure of the ramifications of removing them. */ + if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { +- ast_channel_setoption(other, ntohs(aoh->option), aoh->data, +- f->datalen - sizeof(struct ast_option_header), 0); ++ switch (ntohs(aoh->option)) { ++ case AST_OPTION_TONE_VERIFY: ++ case AST_OPTION_TDD: ++ case AST_OPTION_RELAXDTMF: ++ case AST_OPTION_AUDIO_MODE: ++ ast_channel_setoption(other, ntohs(aoh->option), aoh->data, ++ f->datalen - sizeof(struct ast_option_header), 0); ++ } + } + break; + } diff -Nru asterisk-1.6.2.5/debian/patches/AST-2011-011-1.6.2.diff asterisk-1.6.2.5/debian/patches/AST-2011-011-1.6.2.diff --- asterisk-1.6.2.5/debian/patches/AST-2011-011-1.6.2.diff 1970-01-01 00:00:00.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/AST-2011-011-1.6.2.diff 2011-07-12 19:49:08.000000000 +0000 @@ -0,0 +1,55 @@ +Description: fix account name enumeration +Origin: upstream, http://downloads.asterisk.org/pub/security/AST-2011-011-1.6.2.diff + +Index: asterisk-1.6.2.5/channels/chan_sip.c +=================================================================== +--- asterisk-1.6.2.5.orig/channels/chan_sip.c 2011-07-12 15:48:46.949864020 -0400 ++++ asterisk-1.6.2.5/channels/chan_sip.c 2011-07-12 15:49:06.079864014 -0400 +@@ -12948,9 +12948,9 @@ + { + /* We have to emulate EXACTLY what we'd get with a good peer + * and a bad password, or else we leak information. */ +- const char *response = "407 Proxy Authentication Required"; +- const char *reqheader = "Proxy-Authorization"; +- const char *respheader = "Proxy-Authenticate"; ++ const char *response = "401 Unauthorized"; ++ const char *reqheader = "Authorization"; ++ const char *respheader = "WWW-Authenticate"; + const char *authtoken; + struct ast_str *buf; + char *c; +@@ -12965,23 +12965,18 @@ + [K_LAST] = { NULL, NULL} + }; + +- if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) { +- response = "401 Unauthorized"; +- reqheader = "Authorization"; +- respheader = "WWW-Authenticate"; +- } + authtoken = get_header(req, reqheader); + if (req->ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) { + /* This is a retransmitted invite/register/etc, don't reconstruct authentication + * information */ +- transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0); ++ transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); + /* Schedule auto destroy in 32 seconds (according to RFC 3261) */ + sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); + return; + } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) { + /* We have no auth, so issue challenge and request authentication */ + set_nonce_randdata(p, 1); +- transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0); ++ transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); + /* Schedule auto destroy in 32 seconds */ + sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); + return; +@@ -13225,7 +13220,7 @@ + } + } + } +- if (!peer && sip_cfg.alwaysauthreject) { ++ if (!peer && sip_cfg.alwaysauthreject && ast_test_flag(&p->flags[1], SIP_PAGE2_REGISTERTRYING)) { + /* If we found a peer, we transmit a 100 Trying. Therefore, if we're + * trying to avoid leaking information, we MUST also transmit the same + * response when we DON'T find a peer. */ diff -Nru asterisk-1.6.2.5/debian/patches/dnsmgr-A-SRV-handling asterisk-1.6.2.5/debian/patches/dnsmgr-A-SRV-handling --- asterisk-1.6.2.5/debian/patches/dnsmgr-A-SRV-handling 1970-01-01 00:00:00.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/dnsmgr-A-SRV-handling 2010-07-16 12:07:40.000000000 +0000 @@ -0,0 +1,132 @@ +Description: Resolve handling of A and SRV record changes and problem with multiple A/SRV records returned. +Origin: upstream, https://issues.asterisk.org/file_download.php?file_id=25360&type=bug +Bug: https://issues.asterisk.org/view.php?id=15827 +Bug-Ubuntu: https://launchpad.net/bugs/605358 +Last-Update: 2010-07-14 +--- a/include/asterisk/dnsmgr.h ++++ b/include/asterisk/dnsmgr.h +@@ -42,12 +42,12 @@ + * + * \param name the hostname + * \param result where the DNS manager should store the IP address as it refreshes it. +- * it. ++ * \param service SRV prefix (optional, set to NULL to disable SRV) + * + * This function allocates a new DNS manager entry object, and fills it with the + * provided hostname and IP address. This function does not force an initial lookup +- * of the IP address. So, generally, this should be used when the initial address +- * is already known. ++ * of the IP address. So, this should be used when the initial address ++ * is already known and stored in result. + * + * \return a DNS manager entry + * \version 1.6.1 result changed from struct in_addr to struct sockaddr_in to store port number +@@ -69,6 +69,7 @@ + * \param name the hostname + * \param result where to store the IP address as the DNS manager refreshes it + * \param dnsmgr Where to store the allocate DNS manager entry ++ * \param service SRV prefix (optional, set to NULL to disable SRV) + * + * This function allocates a new DNS manager entry object, and fills it with + * the provided hostname and IP address. This function _does_ force an initial +--- a/main/acl.c ++++ b/main/acl.c +@@ -387,6 +387,7 @@ + } + } + if ((hp = ast_gethostbyname(value, &ahp))) { ++ sin->sin_family = hp->h_addrtype; + memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); + } else { + ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value); +--- a/main/dnsmgr.c ++++ b/main/dnsmgr.c +@@ -52,8 +52,6 @@ + struct ast_dnsmgr_entry { + /*! where we will store the resulting IP address and port number */ + struct sockaddr_in *result; +- /*! the last result, used to check if address/port has changed */ +- struct sockaddr_in last; + /*! SRV record to lookup, if provided. Composed of service, protocol, and domain name: _Service._Proto.Name */ + char *service; + /*! Set to 1 if the entry changes */ +@@ -85,6 +83,9 @@ + .verbose = 0, + }; + ++/* ++ * Allocate a new DNS manager entry ++ */ + struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct sockaddr_in *result, const char *service) + { + struct ast_dnsmgr_entry *entry; +@@ -96,7 +97,6 @@ + entry->result = result; + ast_mutex_init(&entry->lock); + strcpy(entry->name, name); +- memcpy(&entry->last, result, sizeof(entry->last)); + if (service) { + entry->service = ((char *) entry) + sizeof(*entry) + strlen(name); + strcpy(entry->service, service); +@@ -109,6 +109,9 @@ + return entry; + } + ++/* ++ * Free a DNS manager entry ++ */ + void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry) + { + if (!entry) +@@ -123,6 +126,9 @@ + ast_free(entry); + } + ++/* ++ * Allocate a new DNS manager entry and perform the initial lookup before returning ++ */ + int ast_dnsmgr_lookup(const char *name, struct sockaddr_in *result, struct ast_dnsmgr_entry **dnsmgr, const char *service) + { + if (ast_strlen_zero(name) || !result || !dnsmgr) +@@ -133,8 +139,10 @@ + + /* if it's actually an IP address and not a name, + there's no need for a managed lookup */ +- if (inet_aton(name, &result->sin_addr)) ++ if (inet_aton(name, &result->sin_addr)) { ++ result->sin_family = AF_INET; + return 0; ++ } + + ast_verb(4, "doing dnsmgr_lookup for '%s'\n", name); + +@@ -151,7 +159,7 @@ + } + + /* +- * Refresh a dnsmgr entry ++ * Force a refresh of a dnsmgr entry + */ + static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose) + { +@@ -164,15 +172,15 @@ + if (verbose) + ast_verb(3, "refreshing '%s'\n", entry->name); + +- tmp.sin_port = entry->last.sin_port; ++ memset(&tmp, 0, sizeof(tmp)); ++ tmp.sin_port = entry->result->sin_port; + +- if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service) && inaddrcmp(&tmp, &entry->last)) { +- ast_copy_string(iabuf, ast_inet_ntoa(entry->last.sin_addr), sizeof(iabuf)); ++ if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service) && inaddrcmp(&tmp, entry->result)) { ++ ast_copy_string(iabuf, ast_inet_ntoa(entry->result->sin_addr), sizeof(iabuf)); + ast_copy_string(iabuf2, ast_inet_ntoa(tmp.sin_addr), sizeof(iabuf2)); + ast_log(LOG_NOTICE, "dnssrv: host '%s' changed from %s:%d to %s:%d\n", +- entry->name, iabuf, ntohs(entry->last.sin_port), iabuf2, ntohs(tmp.sin_port)); ++ entry->name, iabuf, ntohs(entry->result->sin_port), iabuf2, ntohs(tmp.sin_port)); + *entry->result = tmp; +- entry->last = tmp; + changed = entry->changed = 1; + } + diff -Nru asterisk-1.6.2.5/debian/patches/series asterisk-1.6.2.5/debian/patches/series --- asterisk-1.6.2.5/debian/patches/series 2010-02-03 23:20:36.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/series 2011-07-12 19:49:04.000000000 +0000 @@ -17,3 +17,14 @@ dahdi_ptmp_nt dahdi_pri_debug_spannums sound_files +dnsmgr-A-SRV-handling +unattended_fix +AST-2011-001-1.6.2 +AST-2011-002-1.6.2.diff +AST-2011-003-1.6.2.diff +AST-2011-004-1.6.2.diff +AST-2011-005-1.6.2.diff +AST-2011-006-1.6.2.diff +AST-2011-008.diff +AST-2011-010-1.6.2.diff +AST-2011-011-1.6.2.diff diff -Nru asterisk-1.6.2.5/debian/patches/unattended_fix asterisk-1.6.2.5/debian/patches/unattended_fix --- asterisk-1.6.2.5/debian/patches/unattended_fix 1970-01-01 00:00:00.000000000 +0000 +++ asterisk-1.6.2.5/debian/patches/unattended_fix 2010-12-06 15:55:04.000000000 +0000 @@ -0,0 +1,18 @@ +Index: asterisk-1.6.2.5/channels/chan_local.c +=================================================================== +--- asterisk-1.6.2.5.orig/channels/chan_local.c 2010-12-06 16:37:54.000000000 +0100 ++++ asterisk-1.6.2.5/channels/chan_local.c 2010-12-06 16:54:56.000000000 +0100 +@@ -251,9 +251,10 @@ + } + + if (other) { +- if (other->pbx || other->_bridge || !ast_strlen_zero(other->appl)) { +- ast_queue_frame(other, f); +- } /* else the frame won't go anywhere */ ++ if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_RINGING) { ++ ast_setstate(other, AST_STATE_RINGING); ++ } ++ ast_queue_frame(other, f); + ast_channel_unlock(other); + } +