From b144b5d6d4aa7f094d0fd64091bb35371731c8c5 Mon Sep 17 00:00:00 2001 From: Marc Guasch Date: Thu, 8 Oct 2020 23:59:12 +0200 Subject: [PATCH] Fix function that parses from/to/contact headers (#21672) (#21687) (cherry picked from commit 2d2c4c30f188bb5e20411a61cab9d533b1892328) --- packetbeat/protos/sip/plugin.go | 35 +++++++++++++++++++++------- packetbeat/protos/sip/plugin_test.go | 12 +++++++--- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/packetbeat/protos/sip/plugin.go b/packetbeat/protos/sip/plugin.go index e4cc0364d9a..14b56aeda45 100644 --- a/packetbeat/protos/sip/plugin.go +++ b/packetbeat/protos/sip/plugin.go @@ -499,27 +499,46 @@ func populateBodyFields(m *message, pbf *pb.Fields, fields *ProtocolFields) { func parseFromToContact(fromTo common.NetString) (displayInfo, uri common.NetString, params map[string]common.NetString) { params = make(map[string]common.NetString) - pos := bytes.IndexByte(fromTo, '<') - if pos == -1 { - pos = bytes.IndexByte(fromTo, ' ') - } + fromTo = bytes.TrimSpace(fromTo) + + var uriIsWrapped bool + pos := func() int { + // look for the beginning of a url wrapped in <...> + if pos := bytes.IndexByte(fromTo, '<'); pos > -1 { + uriIsWrapped = true + return pos + } + // if there is no < char, it means there is no display info, and + // that the url starts from the beginning + // https://tools.ietf.org/html/rfc3261#section-20.10 + return 0 + }() displayInfo = bytes.Trim(fromTo[:pos], "'\"\t ") endURIPos := func() int { - if fromTo[pos] == '<' { + if uriIsWrapped { return bytes.IndexByte(fromTo, '>') } return bytes.IndexByte(fromTo, ';') }() + // not wrapped and no header params if endURIPos == -1 { - uri = bytes.TrimRight(fromTo[pos:], ">") - return + uri = fromTo[pos:] + return displayInfo, uri, params } - pos += 1 + + // if wrapped, we want to get over the < char + if uriIsWrapped { + pos += 1 + } + + // if wrapped, we will get the string between <...> + // if not wrapped, we will get the value before the header params (until ;) uri = fromTo[pos:endURIPos] + // parse the header params pos = endURIPos + 1 for _, param := range bytes.Split(fromTo[pos:], []byte(";")) { kv := bytes.SplitN(param, []byte("="), 2) diff --git a/packetbeat/protos/sip/plugin_test.go b/packetbeat/protos/sip/plugin_test.go index fc9ee53aff2..d8c09f5b307 100644 --- a/packetbeat/protos/sip/plugin_test.go +++ b/packetbeat/protos/sip/plugin_test.go @@ -65,11 +65,11 @@ func TestParseFromTo(t *testing.T) { assert.Equal(t, common.NetString(nil), params["tag"]) // From - displayInfo, uri, params = parseFromToContact(common.NetString("\"PCMU/8000\" ;tag=1")) + displayInfo, uri, params = parseFromToContact(common.NetString("\"PCMU/8000\" ;tag=1")) assert.Equal(t, common.NetString("PCMU/8000"), displayInfo) assert.Equal(t, common.NetString("sip:sipp@10.0.2.15:5060"), uri) assert.Equal(t, common.NetString("1"), params["tag"]) - displayInfo, uri, params = parseFromToContact(common.NetString("\"Matthew Hodgson\" ;tag=5c7cdb68")) + displayInfo, uri, params = parseFromToContact(common.NetString(" \"Matthew Hodgson\" ;tag=5c7cdb68")) assert.Equal(t, common.NetString("Matthew Hodgson"), displayInfo) assert.Equal(t, common.NetString("sip:matthew@mxtelecom.com"), uri) assert.Equal(t, common.NetString("5c7cdb68"), params["tag"]) @@ -83,7 +83,7 @@ func TestParseFromTo(t *testing.T) { assert.Equal(t, common.NetString(nil), params["tag"]) // Contact - displayInfo, uri, _ = parseFromToContact(common.NetString("")) + displayInfo, uri, _ = parseFromToContact(common.NetString(" ")) assert.Equal(t, common.NetString(nil), displayInfo) assert.Equal(t, common.NetString("sip:test@10.0.2.15:5060;transport=udp"), uri) displayInfo, uri, params = parseFromToContact(common.NetString(";expires=1200;q=0.500")) @@ -100,6 +100,12 @@ func TestParseFromTo(t *testing.T) { assert.Equal(t, common.NetString("Mr. Watson"), displayInfo) assert.Equal(t, common.NetString("mailto:watson@bell-telephone.com"), uri) assert.Equal(t, common.NetString("0.1"), params["q"]) + + // url is not bounded by <...> + displayInfo, uri, params = parseFromToContact(common.NetString(" sip:test@10.0.2.15:5060;transport=udp")) + assert.Equal(t, common.NetString(nil), displayInfo) + assert.Equal(t, common.NetString("sip:test@10.0.2.15:5060"), uri) + assert.Equal(t, common.NetString("udp"), params["transport"]) } func TestParseUDP(t *testing.T) {