diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 3d57a99adc8cebc7271ccb9aaed4dfc95a439613..e5cd96d90878866cb17f03e2c5cd6d173cc271b1 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1983,12 +1983,56 @@ static int sip_register(char *value, int lineno) return 0; } +static int lws2sws(char *msgbuf, int len) +{ + int h = 0, t = 0; + int lws = 0; + + for (; h < len;) { + /* Eliminate all CRs */ + if (msgbuf[h] == '\r') { + h++; + continue; + } + /* Check for end-of-line */ + if (msgbuf[h] == '\n') { + /* Check for end-of-message */ + if (h + 1 == len) + break; + /* Check for a continuation line */ + if (msgbuf[h + 1] == ' ') { + /* Merge continuation line */ + h++; + continue; + } + /* Propagate LF and start new line */ + msgbuf[t++] = msgbuf[h++]; + lws = 0; + continue; + } + + if (msgbuf[h] == ' ' || msgbuf[h] == '\t') { + if (lws) { + h++; + continue; + } + msgbuf[t++] = msgbuf[h++]; + lws = 1; + continue; + } + msgbuf[t++] = msgbuf[h++]; + if (lws) + lws = 0; + } + msgbuf[t] = '\0'; + return t; +} + static void parse(struct sip_request *req) { /* Divide fields by NULL's */ char *c; int f = 0; - int lastr = 0; c = req->data; /* First header starts immediately */ @@ -2008,25 +2052,13 @@ static void parse(struct sip_request *req) } if (f >= SIP_MAX_HEADERS - 1) { ast_log(LOG_WARNING, "Too many SIP headers...\n"); - } else { - if ((c[1] == ' ') || (c[1] == '\t')) { - /* Continuation of previous header */ - *c = ' '; - if (lastr) { - *(c-1) = ' '; - } - } else { - f++; - req->header[f] = c + 1; - } - } - lastr = 0; + } else + f++; + req->header[f] = c + 1; } else if (*c == '\r') { /* Ignore but eliminate \r's */ *c = 0; - lastr = 1; - } else - lastr = 0; + } c++; } /* Check for last header */ @@ -5824,6 +5856,8 @@ static int sipsock_read(int *id, int fd, short events, void *ignore) req.len = res; if (sipdebug) ast_verbose("\n\nSip read: \n%s\n", req.data); + if (pedanticsipchecking) + req.len = lws2sws(req.data, req.len); parse(&req); if (req.headers < 2) { /* Must have at least two headers */ diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index d852a99d26896f701971107521ff939a8ebfac2c..0c9dd0ebff0bd55d53c1a998322b0a8044c42ce5 100755 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -27,6 +27,8 @@ context = default ; Default context for incoming calls ;srvlookup = yes ; Enable DNS SRV lookups on outbound calls ; Asterisk only uses the first host in SRV records ;pedantic = yes ; Enable slow, pedantic checking for Pingtel + ; and multiline formatted headers for strict + ; SIP compatibility ;tos=lowdelay ; IP QoS parameter, either keyword or value ; like tos=184 ;maxexpirey=3600 ; Max length of incoming registration we allow