chan_sip: Add sendrpid trust options
authorJonathan Rose <jrose@digium.com>
Mon, 21 Apr 2014 16:20:32 +0000 (16:20 +0000)
committerJonathan Rose <jrose@digium.com>
Mon, 21 Apr 2014 16:20:32 +0000 (16:20 +0000)
In r411189, some behavior was changed which made sendrpid behavior
act in a more trusting manner by sending full user data for peers
set with private caller presence in P-Asserted-Identity headers.
Since this changed long time expected behaviors, we decided to pull
that patch when that was pointed out by the community. Instead, this
patch provides a trust_id_outbound setting which will expose the data
per RFC-3325 if set to 'yes' and simply not send the PAI/RPID headers
at all if set to 'no'. By default trust_id_outbound will be set to
'legacy' which will preserve the behavior prior to these patches.
Extra special thanks to Walter Doekes for providing advice and
feedback.

(closes issue AST-1301)

(closes issue ASTERISK-19465)
Reported by: Krzysztof Chmielewski

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

Merged revisions 412744 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 412746 from http://svn.asterisk.org/svn/asterisk/branches/11
........

Merged revisions 412747 from http://svn.asterisk.org/svn/asterisk/branches/12

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@412759 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
channels/chan_sip.c
channels/sip/include/sip.h
configs/sip.conf.sample

diff --git a/CHANGES b/CHANGES
index cacd0a4..58f7949 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -25,6 +25,23 @@ ARI
    a channel's ARI control queue until they are stopped. They also can not
    be rewound or fastforwarded.
 
+chan_sip
+-----------
+ * SIP peers can now specify 'trust_id_outbound' which affects RPID/PAI
+   fields for prohibited callingpres information. Values are legacy, no, and
+   yes. By default, legacy is used.
+   trust_id_outbound=legacy: behavior remains the same as 1.8.26.1 - When
+   dealing with prohibited callingpres, RPID/PAI headers are created for both
+   sendrpid=pai and sendrpid=rpid are appended, but the data is anonymized.
+   When sendrpid=rpid, only the remote party's domain is anonymized.
+   trust_id_outbound=no: when dealing with prohibited callingpres, RPID/PAI
+   headers are not sent.
+   trust_id_outbound=yes: RPID/PAI headers are applied with the full
+   remote party information in tact even for prohibited callingpres
+   information. In the case of PAI, a Privacy: id header will be appended for
+   prohibited calling information to communicate that the private information
+   should not be relayed to untrusted parties.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 12.1.0 to Asterisk 12.2.0 ------------
 ------------------------------------------------------------------------------
@@ -1498,8 +1515,8 @@ sip_to_res_pjsip.py
    a chan_pjsip configuration, but it is expected that configuration beyond
    what the script provides will be needed.
 
-
 ------------------------------------------------------------------------------
+>>>>>>> .merge-right.r412746
 --- Functionality changes from Asterisk 10 to Asterisk 11 --------------------
 ------------------------------------------------------------------------------
 
index e63657f..694ab74 100644 (file)
@@ -12645,15 +12645,39 @@ static int add_rpid(struct sip_request *req, struct sip_pvt *p)
        }
        lid_pres = ast_party_id_presentation(&connected_id);
 
-       fromdomain = S_OR(p->fromdomain, ast_sockaddr_stringify_host_remote(&p->ourip));
+       if (((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) &&
+                       (ast_test_flag(&p->flags[1], SIP_PAGE2_TRUST_ID_OUTBOUND) == SIP_PAGE2_TRUST_ID_OUTBOUND_NO)) {
+               /* If pres is not allowed and we don't trust the peer, we don't apply an RPID header */
+               return 0;
+       }
+
+       fromdomain = p->fromdomain;
+       if (!fromdomain ||
+                       ((ast_test_flag(&p->flags[1], SIP_PAGE2_TRUST_ID_OUTBOUND) == SIP_PAGE2_TRUST_ID_OUTBOUND_YES) &&
+                       !strcmp("anonymous.invalid", fromdomain))) {
+               /* If the fromdomain is NULL or if it was set to anonymous.invalid due to privacy settings and we trust the peer,
+                * use the host IP address */
+               fromdomain = ast_sockaddr_stringify_host_remote(&p->ourip);
+       }
 
        lid_num = ast_uri_encode(lid_num, tmp2, sizeof(tmp2), ast_uri_sip_user);
 
        if (ast_test_flag(&p->flags[0], SIP_SENDRPID_PAI)) {
-               if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) {
-                       ast_str_set(&tmp, -1, "%s", anonymous_string);
-               } else {
+               if (ast_test_flag(&p->flags[1], SIP_PAGE2_TRUST_ID_OUTBOUND) != SIP_PAGE2_TRUST_ID_OUTBOUND_LEGACY) {
+                       /* trust_id_outbound = yes - Always give full information even if it's private, but append a privacy header
+                        * When private data is included */
                        ast_str_set(&tmp, -1, "\"%s\" <sip:%s@%s>", lid_name, lid_num, fromdomain);
+                       if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) {
+                               add_header(req, "Privacy", "id");
+                       }
+               } else {
+                       /* trust_id_outbound = legacy - behave in a non RFC-3325 compliant manner and send anonymized data when
+                        * when handling private data. */
+                       if ((lid_pres & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
+                               ast_str_set(&tmp, -1, "\"%s\" <sip:%s@%s>", lid_name, lid_num, fromdomain);
+                       } else {
+                               ast_str_set(&tmp, -1, "%s", anonymous_string);
+                       }
                }
                add_header(req, "P-Asserted-Identity", ast_str_buffer(tmp));
        } else {
@@ -19643,6 +19667,18 @@ static const char *allowoverlap2str(int mode)
        return map_x_s(allowoverlapstr, mode, "<error>");
 }
 
+static const struct _map_x_s trust_id_outboundstr[] = {
+       { SIP_PAGE2_TRUST_ID_OUTBOUND_LEGACY,  "Legacy" },
+       { SIP_PAGE2_TRUST_ID_OUTBOUND_NO,      "No" },
+       { SIP_PAGE2_TRUST_ID_OUTBOUND_YES,     "Yes" },
+       { -1,                                  NULL }, /* terminator */
+};
+
+static const char *trust_id_outbound2str(int mode)
+{
+       return map_x_s(trust_id_outboundstr, mode, "<error>");
+}
+
 /*! \brief Destroy disused contexts between reloads
        Only used in reload_config so the code for regcontext doesn't get ugly
 */
@@ -20310,6 +20346,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
                        ast_cli(fd, "  Path         : %s\n", ast_str_buffer(path));
                        ast_free(path);
                }
+               ast_cli(fd, "  TrustIDOutbnd: %s\n", trust_id_outbound2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_TRUST_ID_OUTBOUND)));
                ast_cli(fd, "  Subscriptions: %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)));
                ast_cli(fd, "  Overlap dial : %s\n", allowoverlap2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWOVERLAP)));
                if (peer->outboundproxy)
@@ -29863,6 +29900,19 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
        } else if (!strcasecmp(v->name, "rpid_immediate")) {
                ast_set_flag(&mask[1], SIP_PAGE2_RPID_IMMEDIATE);
                ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RPID_IMMEDIATE);
+       } else if (!strcasecmp(v->name, "trust_id_outbound")) {
+               ast_set_flag(&mask[1], SIP_PAGE2_TRUST_ID_OUTBOUND);
+               ast_clear_flag(&flags[1], SIP_PAGE2_TRUST_ID_OUTBOUND);
+               if (!strcasecmp(v->value, "legacy")) {
+                       ast_set_flag(&flags[1], SIP_PAGE2_TRUST_ID_OUTBOUND_LEGACY);
+               } else if (ast_true(v->value)) {
+                       ast_set_flag(&flags[1], SIP_PAGE2_TRUST_ID_OUTBOUND_YES);
+               } else if (ast_false(v->value)) {
+                       ast_set_flag(&flags[1], SIP_PAGE2_TRUST_ID_OUTBOUND_NO);
+               } else {
+                       ast_log(LOG_WARNING, "Unknown trust_id_outbound mode '%s' on line %d, using legacy\n", v->value, v->lineno);
+                       ast_set_flag(&flags[1], SIP_PAGE2_TRUST_ID_OUTBOUND_LEGACY);
+               }
        } else if (!strcasecmp(v->name, "g726nonstandard")) {
                ast_set_flag(&mask[0], SIP_G726_NONSTANDARD);
                ast_set2_flag(&flags[0], ast_true(v->value), SIP_G726_NONSTANDARD);
index 9737806..2659b91 100644 (file)
 #define SIP_PAGE2_HAVEPEERCONTEXT           (1 << 28)   /*< Are we associated with a configured peer context? */
 #define SIP_PAGE2_USE_SRTP                  (1 << 29)   /*!< DP: Whether we should offer (only)  SRTP */
 
+#define SIP_PAGE2_TRUST_ID_OUTBOUND         (3 << 30)   /*!< DP: Do we trust the peer with private presence information? */
+#define SIP_PAGE2_TRUST_ID_OUTBOUND_LEGACY  (0 << 30)   /*!< Legacy, Do not provide private presence information, but include PAI/RPID when private */
+#define SIP_PAGE2_TRUST_ID_OUTBOUND_NO      (1 << 30)   /*!< No, Do not provide private presence information, do not include PAI/RPID when private */
+#define SIP_PAGE2_TRUST_ID_OUTBOUND_YES     (2 << 30)   /*!< Yes, provide private presence information in PAI/RPID headers */
+
 #define SIP_PAGE2_FLAGS_TO_COPY \
        (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_IGNORESDPVERSION | \
        SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | \
        SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_TEXTSUPPORT | SIP_PAGE2_FAX_DETECT | \
        SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS | SIP_PAGE2_PREFERRED_CODEC | \
        SIP_PAGE2_RPID_IMMEDIATE | SIP_PAGE2_RPID_UPDATE | SIP_PAGE2_SYMMETRICRTP |\
-       SIP_PAGE2_Q850_REASON | SIP_PAGE2_HAVEPEERCONTEXT | SIP_PAGE2_USE_SRTP)
+       SIP_PAGE2_Q850_REASON | SIP_PAGE2_HAVEPEERCONTEXT | SIP_PAGE2_USE_SRTP | SIP_PAGE2_TRUST_ID_OUTBOUND)
 
 
 #define SIP_PAGE3_SNOM_AOC               (1 << 0)  /*!< DPG: Allow snom aoc messages */
index 46af790..1175047 100644 (file)
@@ -350,6 +350,17 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
                                 ; transmit such UPDATE messages to it, then you must enable this option.
                                 ; Otherwise, we will have to wait until we can send a reinvite to
                                 ; transmit the information.
+;trust_id_outbound = no         ; Controls whether or not we trust this peer with private identity
+                                ; information (when the remote party has callingpres=prohib or equivalent).
+                                ; no - RPID/PAI headers will not be included for private peer information
+                                ; yes - RPID/PAI headers will include the private peer information. Privacy
+                                ;       requirements will be indicated in a Privacy header for sendrpid=pai
+                                ; legacy - RPID/PAI will be included for private peer information. In the
+                                ;       case of sendrpid=pai, private data that would be included in them
+                                ;       will be anonymized. For sendrpid=rpid, private data may be included
+                                ;       but the remote party's domain will be anonymized. The way legacy
+                                ;       behaves may violate RFC-3325, but it follows historic behavior.
+                                ; This option is set to 'legacy' by default
 ;prematuremedia=no              ; Some ISDN links send empty media frames before 
                                 ; the call is in ringing or progress state. The SIP 
                                 ; channel will then send 183 indicating early media
@@ -1219,6 +1230,7 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
 ; autoframing
 ; insecure
 ; trustrpid
+; trust_id_outbound
 ; progressinband
 ; promiscredir
 ; useclientcode
@@ -1431,7 +1443,8 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
 ;allow=g723.1                    ; Asterisk only supports g723.1 pass-thru!
 ;allow=g729                      ; Pass-thru only unless g729 license obtained
 ;callingpres=allowed_passed_screen ; Set caller ID presentation
-                                 ; See README.callingpres for more information
+                                 ; See function CALLERPRES documentation for possible
+                                 ; values.
 
 ;[xlite1]
 ; Turn off silence suppression in X-Lite ("Transmit Silence"=YES)!