[asterisk-commits] dlee: branch certified-1.8.15 r378936 - in /certified/branches/1.8.15: ./ cha...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Jan 12 01:02:53 CST 2013


Author: dlee
Date: Sat Jan 12 01:02:48 2013
New Revision: 378936

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=378936
Log:
Fix XML encoding of 'identity display' in NOTIFY messages.

XML encoding in chan_sip is accomplished by naively building the XML
directly from strings. While this usually works, it fails to take into
account escaping the reserved characters in XML.

This patch adds an 'ast_xml_escape' function, which works similarly to
'ast_uri_encode'. This is used to properly escape the local_display
attribute in XML formatted NOTIFY messages.

Several things to note:
 * The Right Thing(TM) to do would probably be to replace the
   ast_build_string stuff with building an ast_xml_doc. That's a much
   bigger change, and out of scope for the original ticket, so I
   refrained myself.
 * It is with great sadness that I wrote my own ast_xml_escape
   function. There's one in libxml2, but it's knee-deep in
   libxml2-ness, and not easily used to one-off escape a
   string.
 * I only escaped the string we know is causing problems
   (local_display). At least some of the other strings are
   URI-encoded, which should be XML safe. Rather than figuring out
   what's safe and escaping what's not, it would be much cleaner to
   simply build an ast_xml_doc for the messages and let the XML
   library do the XML escaping. Like I said, that's out of scope.

(closes issue ABE-2902)
Reported by: Guenther Kelleter
Tested by: Guenther Kelleter
Review: http://reviewboard.digium.internal/r/365/

........

Merged revision 378919 from https://origsvn.digium.com/svn/asterisk/be/branches/C.3-bier
........

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

Added:
    certified/branches/1.8.15/tests/test_xml_escape.c
      - copied unchanged from r378933, branches/1.8/tests/test_xml_escape.c
Modified:
    certified/branches/1.8.15/   (props changed)
    certified/branches/1.8.15/channels/chan_sip.c
    certified/branches/1.8.15/include/asterisk/utils.h
    certified/branches/1.8.15/main/utils.c

Propchange: certified/branches/1.8.15/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.

Modified: certified/branches/1.8.15/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/certified/branches/1.8.15/channels/chan_sip.c?view=diff&rev=378936&r1=378935&r2=378936
==============================================================================
--- certified/branches/1.8.15/channels/chan_sip.c (original)
+++ certified/branches/1.8.15/channels/chan_sip.c Sat Jan 12 01:02:48 2013
@@ -12848,7 +12848,8 @@
 		ast_str_append(tmp, 0, "<?xml version=\"1.0\"?>\n");
 		ast_str_append(tmp, 0, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%u\" state=\"%s\" entity=\"%s\">\n", p->dialogver, full ? "full" : "partial", mto);
 		if ((data->state & AST_EXTENSION_RINGING) && sip_cfg.notifyringing) {
-			const char *local_display = exten;
+			/* Twice the extension length should be enough for XML encoding */
+			char local_display[AST_MAX_EXTENSION * 2];
 			char *local_target = ast_strdupa(mto);
 			const char *remote_display = exten;
 			/* It may seem odd to base the remote_target on the To header here,
@@ -12861,6 +12862,8 @@
 			 */
 			char *remote_target = ast_strdupa(mto);
 
+			ast_xml_escape(exten, local_display, sizeof(local_display));
+
 			/* There are some limitations to how this works.  The primary one is that the
 			   callee must be dialing the same extension that is being monitored.  Simply dialing
 			   the hint'd device is not sufficient. */
@@ -12888,8 +12891,9 @@
 					local_target = alloca(need);
 					snprintf(local_target, need, "sip:%s@%s", connected_num, p->fromdomain);
 
-					local_display = ast_strdupa(S_COR(caller->connected.id.name.valid,
-						caller->connected.id.name.str, ""));
+					ast_xml_escape(S_COR(caller->connected.id.name.valid,
+							     caller->connected.id.name.str, ""),
+						       local_display, sizeof(local_display));
 
 					ast_channel_unlock(caller);
 					caller = ast_channel_unref(caller);

Modified: certified/branches/1.8.15/include/asterisk/utils.h
URL: http://svnview.digium.com/svn/asterisk/certified/branches/1.8.15/include/asterisk/utils.h?view=diff&rev=378936&r1=378935&r2=378936
==============================================================================
--- certified/branches/1.8.15/include/asterisk/utils.h (original)
+++ certified/branches/1.8.15/include/asterisk/utils.h Sat Jan 12 01:02:48 2013
@@ -248,9 +248,9 @@
  */
 int ast_base64decode(unsigned char *dst, const char *src, int max);
 
-/*! \brief Turn text string to URI-encoded %XX version 
- *
- * \note 
+/*! \brief Turn text string to URI-encoded %XX version
+ *
+ * \note
  *  At this point, this function is encoding agnostic; it does not
  *  check whether it is fed legal UTF-8. We escape control
  *  characters (\x00-\x1F\x7F), '%', and all characters above 0x7F.
@@ -269,9 +269,23 @@
 char *ast_uri_encode(const char *string, char *outbuf, int buflen, int do_special_char);
 
 /*!	\brief Decode URI, URN, URL (overwrite string)
-	\param s	String to be decoded 
+	\param s	String to be decoded
  */
 void ast_uri_decode(char *s);
+
+/*! ast_xml_escape
+	\brief Escape reserved characters for use in XML.
+
+	If \a outbuf is too short, the output string will be truncated.
+	Regardless, the output will always be null terminated.
+
+	\param string String to be converted
+	\param outbuf Resulting encoded string
+	\param buflen Size of output buffer
+	\return 0 for success
+	\return -1 if buflen is too short.
+ */
+int ast_xml_escape(const char *string, char *outbuf, size_t buflen);
 
 /*!
  * \brief Escape characters found in a quoted string.

Modified: certified/branches/1.8.15/main/utils.c
URL: http://svnview.digium.com/svn/asterisk/certified/branches/1.8.15/main/utils.c?view=diff&rev=378936&r1=378935&r2=378936
==============================================================================
--- certified/branches/1.8.15/main/utils.c (original)
+++ certified/branches/1.8.15/main/utils.c Sat Jan 12 01:02:48 2013
@@ -465,6 +465,69 @@
 			*o = *s;
 	}
 	*o = '\0';
+}
+
+int ast_xml_escape(const char *string, char * const outbuf, const size_t buflen)
+{
+	char *dst = outbuf;
+	char *end = outbuf + buflen - 1; /* save one for the null terminator */
+
+	/* Handle the case for the empty output buffer */
+	if (buflen == 0) {
+		return -1;
+	}
+
+	/* Escaping rules from http://www.w3.org/TR/REC-xml/#syntax */
+	/* This also prevents partial entities at the end of a string */
+	while (*string && dst < end) {
+		const char *entity = NULL;
+		int len = 0;
+
+		switch (*string) {
+		case '<':
+			entity = "&lt;";
+			len = 4;
+			break;
+		case '&':
+			entity = "&amp;";
+			len = 5;
+			break;
+		case '>':
+			/* necessary if ]]> is in the string; easier to escape them all */
+			entity = "&gt;";
+			len = 4;
+			break;
+		case '\'':
+			/* necessary in single-quoted strings; easier to escape them all */
+			entity = "&apos;";
+			len = 6;
+			break;
+		case '"':
+			/* necessary in double-quoted strings; easier to escape them all */
+			entity = "&quot;";
+			len = 6;
+			break;
+		default:
+			*dst++ = *string++;
+			break;
+		}
+
+		if (entity) {
+			ast_assert(len == strlen(entity));
+			if (end - dst < len) {
+				/* no room for the entity; stop */
+				break;
+			}
+			/* just checked for length; strcpy is fine */
+			strcpy(dst, entity);
+			dst += len;
+			++string;
+		}
+	}
+	/* Write null terminator */
+	*dst = '\0';
+	/* If any chars are left in string, return failure */
+	return *string == '\0' ? 0 : -1;
 }
 
 /*! \brief  ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa */




More information about the asterisk-commits mailing list