2 Copyright (C) 2002-2005 Thomas Ries <tries@gmx.net>
4 This file is part of Siproxd.
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.
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.
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
28 #include <netinet/in.h>
30 #include <osipparser2/osip_parser.h>
35 static char const ident[]="$Id: security.c,v 1.19 2005/01/08 10:05:13 hb9xar Exp $";
38 * do security and integrity checks on the received packet
39 * (raw buffer, \0 terminated)
43 * STS_FAILURE if the packed did not pass the checks
45 int security_check_raw(char *sip_buffer, int size) {
46 char *p1=NULL, *p2=NULL;
48 DEBUGC(DBCLASS_BABBLE,"security_check_raw: size=%i", size);
50 * empiric: size must be >= 16 bytes
51 * 2 byte <CR><LF> packets have been seen in the wild
53 if (size<SEC_MINLEN) return STS_FAILURE;
56 * make sure no line (up to the next CRLF) is longer than allowed
57 * empiric: a line should not be longer than 256 characters
58 * (libosip may die with "virtual memory exhausted" otherwise)
59 * Ref: protos test suite c07-sip-r2.jar, test case 203
61 for (p1=sip_buffer; (p1+SEC_MAXLINELEN) < (sip_buffer+size); p1=p2+1) {
63 if ((p2 == 0) || /* no CRLF found */
64 (p2-p1) > SEC_MAXLINELEN) { /* longer than allowed */
65 DEBUGC(DBCLASS_SIP,"security_check_raw: line too long or no "
72 /* As libosip2 is *VERY* sensitive to corrupt input data, we need to
73 do more stuff here. For example, libosip2 can be crashed (with a
74 "<port_malloc.c> virtual memory exhausted" error - God knows why)
75 by sending the following few bytes. It will die in osip_message_parse()
76 ---BUFFER DUMP follows---
77 6e 74 2f 38 30 30 30 0d 0a 61 3d 66 6d 74 70 3a nt/8000..a=fmtp:
78 31 30 31 20 30 2d 31 35 0d 0a 101 0-15..
79 ---end of BUFFER DUMP---
81 By looking at the code in osip_message_parse.c, I'd guess it is
82 the 'only one space present' that leads to a faulty size
83 calculation (VERY BIG NUMBER), which in turn then dies inside
85 So, we need at least 2 spaces to survive that code part of libosip2.
87 p1 = strchr(sip_buffer, ' ');
88 if (p1 && ((p1+1) < (sip_buffer+size))) {
89 p2 = strchr(p1+1, ' ');
91 DEBUGC(DBCLASS_SIP,"security_check_raw: found no space");
95 DEBUGC(DBCLASS_SIP,"security_check_raw: found only one space");
100 /* TODO: still way to go here ... */
106 * do security and integrity checks on the received packet
111 * STS_FAILURE if the packed did not pass the checks
113 int security_check_sip(sip_ticket_t *ticket){
114 osip_message_t *sip=ticket->sipmsg;
115 if (MSG_IS_REQUEST(sip)) {
116 /* check for existing SIP URI in request */
117 if ((sip->req_uri == NULL) || (sip->req_uri->scheme == NULL)) {
118 ERROR("security check failed: NULL SIP URI");
122 /* check SIP URI scheme */
123 if (osip_strcasecmp(sip->req_uri->scheme, "sip")) {
124 ERROR("security check failed: unknown scheme: %s",
125 sip->req_uri->scheme);
131 * Check existence of mandatory headers
134 Rosenberg, et. al. Standards Track [Page 161]
136 RFC 3261 SIP: Session Initiation Protocol June 2002
138 Header field where proxy ACK BYE CAN INV OPT REG
139 ___________________________________________________________
140 Accept R - o - o m* o
141 Accept 2xx - - - o m* o
142 Accept 415 - c - c c c
143 Accept-Encoding R - o - o o o
144 Accept-Encoding 2xx - - - o m* o
145 Accept-Encoding 415 - c - c c c
146 Accept-Language R - o - o o o
147 Accept-Language 2xx - - - o m* o
148 Accept-Language 415 - c - c c c
149 Alert-Info R ar - - - o - -
150 Alert-Info 180 ar - - - o - -
152 Allow 2xx - o - m* m* o
154 Allow 405 - m - m m m
155 Authentication-Info 2xx - o - o o o
156 Authorization R o o o o o o
157 Call-ID c r m m m m m m
158 Call-Info ar - - - o o o
159 Contact R o - - m o o
160 Contact 1xx - - - o - -
161 Contact 2xx - - - m o o
162 Contact 3xx d - o - o o o
163 Contact 485 - o - o o o
164 Content-Disposition o o - o o o
165 Content-Encoding o o - o o o
166 Content-Language o o - o o o
167 Content-Length ar t t t t t t
168 Content-Type * * - * * *
171 Error-Info 300-699 a - o o o o o
174 In-Reply-To R - - - o - -
175 Max-Forwards R amr m m m m m m
176 Min-Expires 423 - - - - - m
177 MIME-Version o o - o o o
178 Organization ar - - - o o o
180 Table 2: Summary of header fields, A--O
187 Rosenberg, et. al. Standards Track [Page 162]
189 RFC 3261 SIP: Session Initiation Protocol June 2002
192 Header field where proxy ACK BYE CAN INV OPT REG
193 ___________________________________________________________________
194 Priority R ar - - - o - -
195 Proxy-Authenticate 407 ar - m - m m m
196 Proxy-Authenticate 401 ar - o o o o o
197 Proxy-Authorization R dr o o - o o o
198 Proxy-Require R ar - o - o o o
199 Record-Route R ar o o o o o -
200 Record-Route 2xx,18x mr - o o o o -
202 Require ar - c - c c c
203 Retry-After 404,413,480,486 - o o o o o
206 Route R adr c c c c c c
208 Subject R - - - o - -
209 Supported R - o o m* o o
210 Supported 2xx - o o m* m* o
211 Timestamp o o o o o o
212 To c(1) r m m m m m m
213 Unsupported 420 - m - m m m
214 User-Agent o o o o o o
215 Via R amr m m m m m m
216 Via rc dr m m m m m m
217 Warning r - o o o o o
218 WWW-Authenticate 401 ar - m - m m m
219 WWW-Authenticate 407 ar - o - o o o
225 * => Mandatory for ALL requests and responses
226 * Call-ID c r m m m m m m
227 * CSeq c r m m m m m m
228 * From c r m m m m m m
229 * To c(1) r m m m m m m
230 * Via R amr m m m m m m
233 /* check for existing Call-ID header */
234 if ((sip->call_id==NULL)||
235 ((sip->call_id->number==NULL)&&(sip->call_id->host==NULL))) {
236 ERROR("security check failed: NULL Call-Id Header");
240 /* check for existing CSeq header */
241 if ((sip->cseq==NULL)||
242 (sip->cseq->method==NULL)||(sip->cseq->number==NULL)) {
243 ERROR("security check failed: NULL CSeq Header");
247 /* check for existing To: header */
248 if ((sip->to==NULL)||
249 (sip->to->url==NULL)||(sip->to->url->host==NULL)) {
250 ERROR("security check failed: NULL To Header");
254 /* check for existing From: header */
255 if ((sip->from==NULL)||
256 (sip->from->url==NULL)||(sip->from->url->host==NULL)) {
257 ERROR("security check failed: NULL From Header");
261 /* check for existing Via: header list */
262 if (sip->vias==NULL) {
263 ERROR("security check failed: No Via Headers");
269 /* TODO: still way to go here ... */