<p>dexter has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/9474">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">protocol: reject illegal multiple lco options<br><br>At the moment osmo-mgw will accept multiple lco options. (e.g.<br>p:10, a:PCMU, p:10) If LCO appear multiple times, than the first<br>appearance of will be parsed and used, all following appearances<br>will be ignored. However, having multiple appearances of LCO is<br>illegal and affected requests should be rejected.<br><br>- make sure that multiple appearances of LCOs will be rejected<br><br>Change-Id: Iae2fddfa5f2bcfc952f8ab217b3056694e5f7812<br>Closes: OS#3119<br>---<br>M src/libosmo-mgcp/mgcp_protocol.c<br>1 file changed, 98 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-mgw refs/changes/74/9474/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>index 9fdaf18..8eaff3b 100644</span><br><span>--- a/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>+++ b/src/libosmo-mgcp/mgcp_protocol.c</span><br><span>@@ -395,6 +395,97 @@</span><br><span>         return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Helper function for check_local_cx_options() to get a pointer of the next</span><br><span style="color: hsl(120, 100%, 40%);">+ * lco option identifier */</span><br><span style="color: hsl(120, 100%, 40%);">+static char *get_lco_identifier(const char *options)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       char *ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+    unsigned int count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     ptr = strstr(options, ":");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ptr)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Endless loop protection */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (count > 10000)</span><br><span style="color: hsl(120, 100%, 40%);">+                 return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          if (ptr <= options)</span><br><span style="color: hsl(120, 100%, 40%);">+                        break;</span><br><span style="color: hsl(120, 100%, 40%);">+                else if (*ptr == ' ' || *ptr == ',') {</span><br><span style="color: hsl(120, 100%, 40%);">+                        ptr++;</span><br><span style="color: hsl(120, 100%, 40%);">+                        break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             ptr--;</span><br><span style="color: hsl(120, 100%, 40%);">+                count++;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Check the LCO option. This function checks for multiple appearence of LCO</span><br><span style="color: hsl(120, 100%, 40%);">+ * options, which is illegal */</span><br><span style="color: hsl(120, 100%, 40%);">+int check_local_cx_options(void *ctx, const char *options)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        char *options_copy;</span><br><span style="color: hsl(120, 100%, 40%);">+   char *lco_identifier;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *lco_identifier_end;</span><br><span style="color: hsl(120, 100%, 40%);">+     char *next_lco_identifier;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  char **lco_seen;</span><br><span style="color: hsl(120, 100%, 40%);">+      unsigned int lco_seen_n = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!options)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  lco_seen = (char **)talloc_zero_size(ctx, strlen(options) * sizeof(char *));</span><br><span style="color: hsl(120, 100%, 40%);">+  options_copy = talloc_strdup(ctx, options);</span><br><span style="color: hsl(120, 100%, 40%);">+   lco_identifier = options_copy;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      do {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* Move the lco_identifier pointer to the beginning of the</span><br><span style="color: hsl(120, 100%, 40%);">+             * current lco option identifier */</span><br><span style="color: hsl(120, 100%, 40%);">+           lco_identifier = get_lco_identifier(lco_identifier);</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!lco_identifier)</span><br><span style="color: hsl(120, 100%, 40%);">+                  goto error;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Look ahead to the next LCO option early, since we</span><br><span style="color: hsl(120, 100%, 40%);">+           * will parse destructively */</span><br><span style="color: hsl(120, 100%, 40%);">+                next_lco_identifier = strstr(lco_identifier + 1, ",");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Pinch off the end of the lco field identifier name</span><br><span style="color: hsl(120, 100%, 40%);">+          * and see if we still got something */</span><br><span style="color: hsl(120, 100%, 40%);">+               lco_identifier_end = strstr(lco_identifier, ":");</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!lco_identifier_end)</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto error;</span><br><span style="color: hsl(120, 100%, 40%);">+           *lco_identifier_end = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+           if (strlen(lco_identifier) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto error;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Check if we have already seen the current field identifier</span><br><span style="color: hsl(120, 100%, 40%);">+          * before. If yes, we must bail, an LCO must only appear once</span><br><span style="color: hsl(120, 100%, 40%);">+          * in the LCO string */</span><br><span style="color: hsl(120, 100%, 40%);">+               for (i = 0; i < lco_seen_n; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (strcmp(lco_seen[i], lco_identifier) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                         goto error;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+             lco_seen[lco_seen_n] = lco_identifier;</span><br><span style="color: hsl(120, 100%, 40%);">+                lco_seen_n++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Go to the next lco option */</span><br><span style="color: hsl(120, 100%, 40%);">+               lco_identifier = next_lco_identifier;</span><br><span style="color: hsl(120, 100%, 40%);">+ } while (lco_identifier);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   talloc_free(lco_seen);</span><br><span style="color: hsl(120, 100%, 40%);">+        talloc_free(options_copy);</span><br><span style="color: hsl(120, 100%, 40%);">+    return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+error:</span><br><span style="color: hsl(120, 100%, 40%);">+     talloc_free(lco_seen);</span><br><span style="color: hsl(120, 100%, 40%);">+        talloc_free(options_copy);</span><br><span style="color: hsl(120, 100%, 40%);">+    return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Set the LCO from a string (see RFC 3435).</span><br><span>  * The string is stored in the 'string' field. A NULL string is handled exactly</span><br><span>  * like an empty string, the 'string' field is never NULL after this function</span><br><span>@@ -410,6 +501,13 @@</span><br><span>   if (strlen(options) == 0)</span><br><span>            return 0;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Make sure the encoding of the LCO is consistant before we proceed */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (check_local_cx_options(ctx, options) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DLMGCP, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                   "local CX options: Internal inconsistency in Local Connection Options!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return 524;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  p_opt = strstr(options, "p:");</span><br><span>     if (p_opt && sscanf(p_opt, "p:%d-%d",</span><br><span>                          &lco->pkt_period_min, &lco->pkt_period_max) == 1)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/9474">change 9474</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/9474"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-mgw </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Iae2fddfa5f2bcfc952f8ab217b3056694e5f7812 </div>
<div style="display:none"> Gerrit-Change-Number: 9474 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>