1 /*
2     Copyright (C) 2002-2008  Thomas Ries <tries@gmx.net>
3 
4     This file is part of Siproxd.
5 
6     Siproxd is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     Siproxd is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with Siproxd; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20 
21 #include "config.h"
22 
23 #include <stdio.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <netinet/in.h>
29 
30 #include <osipparser2/osip_parser.h>
31 
32 #include "siproxd.h"
33 #include "log.h"
34 
35 static char const ident[]="$Id: security.c 443 2010-01-07 11:31:56Z hb9xar $";
36 
37 /*
38  * do security and integrity checks on the received packet
39  * (raw buffer, \0 terminated)
40  *
41  * RETURNS
42  *	STS_SUCCESS if ok
43  * 	STS_FAILURE if the packed did not pass the checks
44  */
security_check_raw(char * sip_buffer,size_t size)45 int security_check_raw(char *sip_buffer, size_t size) {
46    char *p1=NULL, *p2=NULL;
47 
48    DEBUGC(DBCLASS_BABBLE,"security_check_raw: size=%ld", (long)size);
49    /*
50     * empiric: size must be >= 16 bytes
51     *   2 byte <CR><LF> packets have been seen in the wild
52     *   also 4 bytes with 0x00 (seem to be used to keep potential UDP
53     *   masquerading tunnels open)
54     */
55    if (size<SEC_MINLEN) return STS_FAILURE;
56 
57    /*
58     * make sure no line (up to the next CRLF) is longer than allowed
59     * empiric: a line should not be longer than 256 characters
60     * (libosip may die with "virtual memory exhausted" otherwise)
61     * Ref: protos test suite c07-sip-r2.jar, test case 203
62     * !! Contact records may all come in one single line, getting QUITE long...
63     *    especially on TCP.
64     */
65    for (p1=sip_buffer; (p1+SEC_MAXLINELEN) < (sip_buffer+size); p1=p2+1) {
66       p2=strchr(p1, 10);
67       if ((p2 == 0) ||                  /* no CRLF found */
68           (p2-p1) > SEC_MAXLINELEN) {   /* longer than allowed */
69          DEBUGC(DBCLASS_SIP,"security_check_raw: line too long or no "
70                             "CRLF found");
71          return STS_FAILURE;
72       }
73    }
74 
75 
76    /* As libosip2 is *VERY* sensitive to corrupt input data, we need to
77       do more stuff here. For example, libosip2 can be crashed (with a
78       "<port_malloc.c> virtual memory exhausted" error - God knows why)
79       by sending the following few bytes. It will die in osip_message_parse()
80       ---BUFFER DUMP follows---
81         6e 74 2f 38 30 30 30 0d 0a 61 3d 66 6d 74 70 3a nt/8000..a=fmtp:
82         31 30 31 20 30 2d 31 35 0d 0a                   101 0-15..
83       ---end of BUFFER DUMP---
84 
85       By looking at the code in osip_message_parse.c, I'd guess it is
86       the 'only one space present' that leads to a faulty size
87       calculation (VERY BIG NUMBER), which in turn then dies inside
88       osip_malloc.
89       So, we need at least 2 spaces to survive that code part of libosip2.
90     */
91    p1 = strchr(sip_buffer, ' ');
92    if (p1 && ((p1+1) < (sip_buffer+size))) {
93       p2 = strchr(p1+1, ' ');
94    } else {
95          DEBUGC(DBCLASS_SIP,"security_check_raw: found no space");
96          return STS_FAILURE;
97    }
98    if (p2==NULL) {
99          DEBUGC(DBCLASS_SIP,"security_check_raw: found only one space");
100          return STS_FAILURE;
101    }
102 
103    /* libosip2 can be put into an endless loop by trying to parse:
104       ---BUFFER DUMP follows---
105         49 4e 56 49 54 45 20 20 53 49 50 2f 32 2e 30 0d INVITE  SIP/2.0.
106         0a 56 69 61 3a 20 53 49 50 2f 32 2e 30 2f 55 44 .Via: SIP/2.0/UD
107    Note, this is an INVITE with no valid SIP URI (INVITE  SIP/2.0)
108    */
109    /* clumsy... */
110    if (size >20) {
111    if      (strncmp(sip_buffer, "INVITE  SIP/2.0",  15)==0) return STS_FAILURE;
112    else if (strncmp(sip_buffer, "ACK  SIP/2.0",     12)==0) return STS_FAILURE;
113    else if (strncmp(sip_buffer, "BYE  SIP/2.0",     12)==0) return STS_FAILURE;
114    else if (strncmp(sip_buffer, "CANCEL  SIP/2.0",  15)==0) return STS_FAILURE;
115    else if (strncmp(sip_buffer, "REGISTER  SIP/2.0",17)==0) return STS_FAILURE;
116    else if (strncmp(sip_buffer, "OPTIONS  SIP/2.0", 16)==0) return STS_FAILURE;
117    else if (strncmp(sip_buffer, "INFO  SIP/2.0",    13)==0) return STS_FAILURE;
118    }
119 
120    /* TODO: still way to go here ... */
121    return STS_SUCCESS;
122 }
123 
124 
125 /*
126  * do security and integrity checks on the received packet
127  * (parsed buffer)
128  *
129  * RETURNS
130  *	STS_SUCCESS if ok
131  * 	STS_FAILURE if the packed did not pass the checks
132  */
security_check_sip(sip_ticket_t * ticket)133 int security_check_sip(sip_ticket_t *ticket){
134    osip_message_t *sip=ticket->sipmsg;
135    if (MSG_IS_REQUEST(sip)) {
136       /* check for existing SIP URI in request */
137       if ((sip->req_uri == NULL) || (sip->req_uri->scheme == NULL)) {
138          ERROR("security check failed: NULL SIP URI");
139          return STS_FAILURE;
140       }
141 
142       /* check SIP URI scheme */
143       if (osip_strcasecmp(sip->req_uri->scheme, "sip")) {
144          ERROR("security check failed: unknown scheme: %s",
145                sip->req_uri->scheme);
146          return STS_FAILURE;
147       }
148    }
149 
150    /*
151     * Check existence of mandatory headers
152     *
153 
154 Rosenberg, et. al.          Standards Track                   [Page 161]
155 
156 RFC 3261            SIP: Session Initiation Protocol           June 2002
157 
158       Header field          where   proxy ACK BYE CAN INV OPT REG
159       ___________________________________________________________
160       Accept                  R            -   o   -   o   m*  o
161       Accept                 2xx           -   -   -   o   m*  o
162       Accept                 415           -   c   -   c   c   c
163       Accept-Encoding         R            -   o   -   o   o   o
164       Accept-Encoding        2xx           -   -   -   o   m*  o
165       Accept-Encoding        415           -   c   -   c   c   c
166       Accept-Language         R            -   o   -   o   o   o
167       Accept-Language        2xx           -   -   -   o   m*  o
168       Accept-Language        415           -   c   -   c   c   c
169       Alert-Info              R      ar    -   -   -   o   -   -
170       Alert-Info             180     ar    -   -   -   o   -   -
171       Allow                   R            -   o   -   o   o   o
172       Allow                  2xx           -   o   -   m*  m*  o
173       Allow                   r            -   o   -   o   o   o
174       Allow                  405           -   m   -   m   m   m
175       Authentication-Info    2xx           -   o   -   o   o   o
176       Authorization           R            o   o   o   o   o   o
177       Call-ID                 c       r    m   m   m   m   m   m
178       Call-Info                      ar    -   -   -   o   o   o
179       Contact                 R            o   -   -   m   o   o
180       Contact                1xx           -   -   -   o   -   -
181       Contact                2xx           -   -   -   m   o   o
182       Contact                3xx      d    -   o   -   o   o   o
183       Contact                485           -   o   -   o   o   o
184       Content-Disposition                  o   o   -   o   o   o
185       Content-Encoding                     o   o   -   o   o   o
186       Content-Language                     o   o   -   o   o   o
187       Content-Length                 ar    t   t   t   t   t   t
188       Content-Type                         *   *   -   *   *   *
189       CSeq                    c       r    m   m   m   m   m   m
190       Date                            a    o   o   o   o   o   o
191       Error-Info           300-699    a    -   o   o   o   o   o
192       Expires                              -   -   -   o   -   o
193       From                    c       r    m   m   m   m   m   m
194       In-Reply-To             R            -   -   -   o   -   -
195       Max-Forwards            R      amr   m   m   m   m   m   m
196       Min-Expires            423           -   -   -   -   -   m
197       MIME-Version                         o   o   -   o   o   o
198       Organization                   ar    -   -   -   o   o   o
199 
200              Table 2: Summary of header fields, A--O
201 
202 
203 
204 
205 
206 
207 Rosenberg, et. al.          Standards Track                   [Page 162]
208 
209 RFC 3261            SIP: Session Initiation Protocol           June 2002
210 
211 
212    Header field              where       proxy ACK BYE CAN INV OPT REG
213    ___________________________________________________________________
214    Priority                    R          ar    -   -   -   o   -   -
215    Proxy-Authenticate         407         ar    -   m   -   m   m   m
216    Proxy-Authenticate         401         ar    -   o   o   o   o   o
217    Proxy-Authorization         R          dr    o   o   -   o   o   o
218    Proxy-Require               R          ar    -   o   -   o   o   o
219    Record-Route                R          ar    o   o   o   o   o   -
220    Record-Route             2xx,18x       mr    -   o   o   o   o   -
221    Reply-To                                     -   -   -   o   -   -
222    Require                                ar    -   c   -   c   c   c
223    Retry-After          404,413,480,486         -   o   o   o   o   o
224                             500,503             -   o   o   o   o   o
225                             600,603             -   o   o   o   o   o
226    Route                       R          adr   c   c   c   c   c   c
227    Server                      r                -   o   o   o   o   o
228    Subject                     R                -   -   -   o   -   -
229    Supported                   R                -   o   o   m*  o   o
230    Supported                  2xx               -   o   o   m*  m*  o
231    Timestamp                                    o   o   o   o   o   o
232    To                        c(1)          r    m   m   m   m   m   m
233    Unsupported                420               -   m   -   m   m   m
234    User-Agent                                   o   o   o   o   o   o
235    Via                         R          amr   m   m   m   m   m   m
236    Via                        rc          dr    m   m   m   m   m   m
237    Warning                     r                -   o   o   o   o   o
238    WWW-Authenticate           401         ar    -   m   -   m   m   m
239    WWW-Authenticate           407         ar    -   o   -   o   o   o
240 
241 */
242 
243 
244   /*
245    * => Mandatory for ALL requests and responses
246    * Call-ID                 c       r    m   m   m   m   m   m
247    * CSeq                    c       r    m   m   m   m   m   m
248    * From                    c       r    m   m   m   m   m   m
249    * To                      c(1)    r    m   m   m   m   m   m
250    * Via                     R      amr   m   m   m   m   m   m
251    */
252 
253   /* check for existing Call-ID header */
254    if ((sip->call_id==NULL)||
255        ((sip->call_id->number==NULL)&&(sip->call_id->host==NULL))) {
256       ERROR("security check failed: NULL Call-Id Header");
257       return STS_FAILURE;
258    }
259 
260   /* check for existing CSeq header */
261    if ((sip->cseq==NULL)||
262        (sip->cseq->method==NULL)||(sip->cseq->number==NULL)) {
263       ERROR("security check failed: NULL CSeq Header");
264       return STS_FAILURE;
265    }
266 
267    /* check for existing To: header */
268    if ((sip->to==NULL)||
269        (sip->to->url==NULL)||(sip->to->url->host==NULL)) {
270       ERROR("security check failed: NULL To Header");
271       return STS_FAILURE;
272    }
273 
274   /* check for existing From: header */
275    if ((sip->from==NULL)||
276        (sip->from->url==NULL)||(sip->from->url->host==NULL)) {
277       ERROR("security check failed: NULL From Header");
278       return STS_FAILURE;
279    }
280 
281 
282 
283    /* TODO: still way to go here ... */
284    return STS_SUCCESS;
285 }
286