Author: Terry Wilson <twilson@digium.com>
Date: Mon, 21 Nov 2011 20:23:55 +0000
Subject: Default to nat=yes; warn when nat in general and peer differ
Bug: https://issues.asterisk.org/jira/browse/ASTERISK-18862
Origin: http://svnview.digium.com/svn/asterisk?view=rev&rev=345800

It is possible to enumerate SIP usernames when the general and user/peer
nat settings differ in whether to respond to the port a request is sent
from or the port listed for responses in the Via header. In 1.4 and 1.6.2,
this would mean if one setting was nat=yes or nat=route and the other was
either nat=no or nat=never. In 1.8 and 10, this would mean when one was
nat=force_rport and the other was nat=no.

In order to address this problem, it was decided to switch the default
behavior to nat=yes/force_rport as it is the most commonly used option
and to strongly discourage setting nat per-peer/user when at all possible.

For more discussion of the issue, please see:
  http://lists.digium.com/pipermail/asterisk-dev/2011-November/052191.html

Review: https://reviewboard.asterisk.org/r/1591/

---
 CHANGES                 |   12 ++++++++++++
 channels/chan_sip.c     |   37 +++++++++++++++++++++++++------------
 configs/sip.conf.sample |   17 +++++++++--------
 3 files changed, 46 insertions(+), 20 deletions(-)

--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,18 @@
 ======================================================================
 
 ------------------------------------------------------------------------------
+--- Functionality changes since Asterisk 1.6.2.20                -------------
+------------------------------------------------------------------------------
+
+SIP Changes
+-----------
+    * Due to potential username discovery vulnerabilities, the 'nat' setting in sip.conf
+      now defaults to yes. It is very important that phones requiring nat=no be
+      specifically set as such instead of relying on the default setting. If at all
+      possible, all devices should have nat settings configured in the general section as
+      opposed to configuring nat per-device.
+
+------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 1.6.1 to Asterisk 1.6.2  -------------
 ------------------------------------------------------------------------------
 
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -23568,15 +23568,14 @@ static int handle_common_options(struct
 		}
 	} else if (!strcasecmp(v->name, "nat")) {
 		ast_set_flag(&mask[0], SIP_NAT);
-		ast_clear_flag(&flags[0], SIP_NAT);
-		if (!strcasecmp(v->value, "never"))
-			ast_set_flag(&flags[0], SIP_NAT_NEVER);
-		else if (!strcasecmp(v->value, "route"))
-			ast_set_flag(&flags[0], SIP_NAT_ROUTE);
-		else if (ast_true(v->value))
-			ast_set_flag(&flags[0], SIP_NAT_ALWAYS);
-		else
-			ast_set_flag(&flags[0], SIP_NAT_RFC3581);
+		ast_set_flag(&flags[0], SIP_NAT_ALWAYS);
+		if (!strcasecmp(v->value, "never")) {
+			ast_set_flags_to(&flags[0], SIP_NAT, SIP_NAT_NEVER);
+		} else if (!strcasecmp(v->value, "route")) {
+			ast_set_flags_to(&flags[0], SIP_NAT, SIP_NAT_ROUTE);
+		} else if (ast_false(v->value)) {
+			ast_set_flags_to(&flags[0], SIP_NAT, SIP_NAT_RFC3581);
+		}
 	} else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
 		ast_set_flag(&mask[0], SIP_REINVITE);
 		ast_clear_flag(&flags[0], SIP_REINVITE);
@@ -24491,6 +24490,15 @@ static int peer_markall_func(void *devic
 	return 0;
 }
 
+static void display_nat_warning(const char *cat, int reason, struct ast_flags *flags) {
+	int global_nat, specific_nat;
+
+	if (reason == CHANNEL_MODULE_LOAD && (specific_nat = ast_test_flag(&flags[0], SIP_NAT)) != (global_nat = ast_test_flag(&global_flags[0], SIP_NAT))) {
+		ast_log(LOG_WARNING, "sip.conf: Different 'nat' settings between [general] and section [%s]. See /usr/share/doc/asterisk/README.Debian.gz (global='%s' peer/user='%s')\n",
+				cat, nat2str(global_nat), nat2str(specific_nat));
+	}
+}
+
 /*! \brief Re-read SIP.conf config file
 \note	This function reloads all config data, except for
 	active peers (with registrations). They will only
@@ -24705,9 +24713,10 @@ static int reload_config(enum channelrel
 	ast_copy_string(default_mohinterpret, DEFAULT_MOHINTERPRET, sizeof(default_mohinterpret));
 	ast_copy_string(default_mohsuggest, DEFAULT_MOHSUGGEST, sizeof(default_mohsuggest));
 	ast_copy_string(default_vmexten, DEFAULT_VMEXTEN, sizeof(default_vmexten));
-	ast_set_flag(&global_flags[0], SIP_DTMF_RFC2833);			/*!< Default DTMF setting: RFC2833 */
-	ast_set_flag(&global_flags[0], SIP_NAT_RFC3581);			/*!< NAT support if requested by device with rport */
-	ast_set_flag(&global_flags[0], SIP_DIRECT_MEDIA);			/*!< Allow re-invites */
+	ast_set_flag(&global_flags[0], SIP_DTMF_RFC2833); /*!< Default DTMF setting: RFC2833 */
+	ast_set_flag(&global_flags[0], SIP_NAT_RFC3581);  /*!< NAT support if requested by device with rport */
+	ast_set_flag(&global_flags[0], SIP_DIRECT_MEDIA); /*!< Allow re-invites */
+	ast_set_flag(&global_flags[0], SIP_NAT_ALWAYS);   /*!< Default to nat=yes */
 
 	/* Debugging settings, always default to off */
 	dumphistory = FALSE;
@@ -25301,6 +25310,7 @@ static int reload_config(enum channelrel
 			}
 			peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0, 0);
 			if (peer) {
+				display_nat_warning(cat, reason, &peer->flags[0]);
 				ao2_t_link(peers, peer, "link peer into peers table");
 				if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) {
 					ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
--- a/configs/sip.conf.sample
+++ b/configs/sip.conf.sample
@@ -656,10 +656,18 @@ srvlookup=yes                   ; Enable
 ; The following settings are allowed (both globally and in individual sections):
 ;
 ;        nat = no                ; default. Use NAT mode only according to RFC3581 (;rport)
-;        nat = yes               ; Always ignore info and assume NAT
+;        nat = yes               ; Always ignore info and assume NAT (default)
 ;        nat = never             ; Never attempt NAT mode or RFC3581 support
 ;        nat = route             ; route = Assume NAT, don't send rport 
 ;                                ; (work around more UNIDEN bugs)
+;
+; IT IS IMPORTANT TO NOTE that if the nat setting in the general section differs from
+; the nat setting in a peer definition, then the peer username will be discoverable
+; by outside parties as Asterisk will respond to different ports for defined and
+; undefined peers. For this reason it is recommended to ONLY DEFINE NAT SETTINGS IN THE
+; GENERAL SECTION. Specifically, if nat=route or nat=yes in one section and nat=no or
+; nat=never in the other, then valid users with settings differing from those in the
+; general section will be discoverable.
 
 ;----------------------------------- MEDIA HANDLING --------------------------------
 ; By default, Asterisk tries to re-invite media streams to an optimal path. If there's
@@ -982,12 +990,10 @@ srvlookup=yes                   ; Enable
         type=friend
 
 [natted-phone](!,basic-options)   ; another template inheriting basic-options
-        nat=yes
         directmedia=no
         host=dynamic
 
 [public-phone](!,basic-options)   ; another template inheriting basic-options
-        nat=no
         directmedia=yes
 
 [my-codecs](!)                    ; a template for my preferred codecs
@@ -1022,7 +1028,6 @@ srvlookup=yes                   ; Enable
                                  ; on incoming calls to Asterisk
 ;host=192.168.0.23               ; we have a static but private IP address
                                  ; No registration allowed
-;nat=no                          ; there is not NAT between phone and Asterisk
 ;directmedia=yes                 ; allow RTP voice traffic to bypass Asterisk
 ;dtmfmode=info                   ; either RFC2833 or INFO for the BudgeTone
 ;call-limit=1                    ; permit only 1 outgoing call and 1 incoming call at a time
@@ -1052,7 +1057,6 @@ srvlookup=yes                   ; Enable
 ;regexten=1234                   ; When they register, create extension 1234
 ;callerid="Jane Smith" <5678>
 ;host=dynamic                    ; This device needs to register
-;nat=yes                         ; X-Lite is behind a NAT router
 ;directmedia=no                  ; Typically set to NO if behind NAT
 ;disallow=all
 ;allow=gsm                       ; GSM consumes far less bandwidth than ulaw
@@ -1123,9 +1127,6 @@ srvlookup=yes                   ; Enable
 ;type=friend
 ;secret=blah
 ;qualify=200                     ; Qualify peer is no more than 200ms away
-;nat=yes                         ; This phone may be natted
-                                 ; Send SIP and RTP to the IP address that packet is 
-                                 ; received from instead of trusting SIP headers 
 ;host=dynamic                    ; This device registers with us
 ;directmedia=no                  ; Asterisk by default tries to redirect the
                                  ; RTP media stream (audio) to go directly from
