233128939c9de6d7d5be1ef7808ec1c9ad718033
[sip-router] / modules / sanity / sanity.c
1 /*
2  * $Id$
3  *
4  * Sanity Checks Module
5  *
6  * Copyright (C) 2006 iptelorg GbmH
7  *
8  * This file is part of ser, a free SIP server.
9  *
10  * ser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * For a license to use the ser software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * ser is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  *
29  */
30
31 #include "mod_sanity.h"
32 #include "sanity.h"
33 #include "../../ut.h"
34 #include "../../trim.h"
35 #include "../../data_lump_rpl.h"
36 #include "../../mem/mem.h"
37 #include "../../parser/parse_uri.h"
38 #include "../../parser/parse_expires.h"
39 #include "../../parser/parse_content.h"
40 #include "../../parser/digest/digest.h"
41 #include "../../parser/contact/parse_contact.h"
42 #include "../../parser/parse_to.h"
43 #include "../../parser/parse_from.h"
44
45 #define UNSUPPORTED_HEADER "Unsupported: "
46 #define UNSUPPORTED_HEADER_LEN (sizeof(UNSUPPORTED_HEADER)-1)
47
48
49 /**
50  * wrapper to SL send reply function
51  * - check if it is the case for sending a reply before doing it
52  */
53 int sanity_reply(sip_msg_t *msg, int code, char *reason)
54 {
55         if(msg->first_line.type == SIP_REPLY) {
56                 return 1;
57         }
58
59         if(msg->REQ_METHOD == METHOD_ACK) {
60                 return 1;
61         }
62         if(slb.zreply(msg, code, reason) < 0) {
63                 return -1;
64         }
65         return 0;
66 }
67
68 /* check if the given string is a valid unsigned int value */
69 int str2valid_uint(str* _number, unsigned int* _result) {
70         int i;
71         int result= 0;
72         int equal = 1;
73         char mui[10] = "4294967296";
74
75         *_result = 0;
76         if (_number->len > 10) {
77 #ifdef EXTRA_DEBUG
78                 DBG("valid_uint(): number is too long\n");
79 #endif
80                 return -1;
81         }
82         if (_number->len < 10) {
83                 equal = 0;
84         }
85         for (i=0; i < _number->len; i++) {
86                 if (_number->s[i] < '0' || _number->s[i] > '9') {
87 #ifdef EXTRA_DEBUG
88                         DBG("valid_uint(): number contains non-number char\n");
89 #endif
90                         return -1;
91                 }
92                 if (equal == 1) {
93                         if (_number->s[i] < mui[i]) {
94                                 equal = 0;
95                         }
96                         else if (_number->s[i] > mui[i]) {
97 #ifdef EXTRA_DEBUG
98                                 DBG("valid_uint(): number exceeds uint\n");
99 #endif
100                                 return -1;
101                         }
102                 }
103                 result *= 10;
104                 result += _number->s[i] - '0';
105         }
106         *_result = result;
107         return 0;
108 }
109
110 /* parses the given comma seperated string into a string list */
111 strl* parse_str_list(str* _string) {
112         str input;
113         strl *parsed_list, *pl;
114         char *comma;
115
116         /* make a copy because we trim it */
117         input.s = _string->s;
118         input.len = _string->len;
119
120         trim(&input);
121
122         if (input.len == 0) {
123 #ifdef EXTRA_DEBUG
124                 DBG("parse_str_list: list is empty\n");
125 #endif
126                 return NULL;
127         }
128         parsed_list = pkg_malloc(sizeof(strl));
129         if (parsed_list == NULL) {
130                 LOG(L_ERR, "parse_str_list: OUT OF MEMORY for initial list element\n");
131                 return NULL;
132         }
133         memset(parsed_list, 0, sizeof(strl));
134         parsed_list->string.s = input.s;
135         parsed_list->string.len = input.len;
136
137         comma = q_memchr(input.s, ',', input.len);
138         pl = parsed_list;
139         while (comma != NULL) {
140                 pl->next = pkg_malloc(sizeof(strl));
141                 if (pl->next == NULL) {
142                         LOG(L_ERR, "parse_str_list: OUT OF MEMORY for further list"
143                                         " element\n");
144                         return parsed_list;
145                 }
146                 memset(pl->next, 0, sizeof(strl));
147                 pl->next->string.s = comma + 1;
148                 pl->next->string.len = pl->string.len
149                                                                         - (pl->next->string.s - pl->string.s);
150                 pl->string.len = comma - pl->string.s;
151                 trim_trailing(&(pl->string));
152                 pl = pl->next;
153                 trim_leading(&(pl->string));
154                 comma = q_memchr(pl->string.s, ',', pl->string.len);
155         }
156
157         return parsed_list;
158 }
159
160 /* free the elements of the linked str list */
161 void free_str_list(strl *_list) {
162         strl *cur, *next;
163
164         if (_list != NULL) {
165                 cur = _list;
166                 while (cur != NULL) {
167                         next = cur->next;
168                         pkg_free(cur);
169                         cur = next;
170                 }
171         }
172 }
173
174 int parse_proxyrequire(struct hdr_field* _h) {
175         strl *pr_l;
176
177         if (_h->parsed) {
178                 return 0; /* Already parsed */
179         }
180
181         if ((pr_l = parse_str_list(&(_h->body))) == NULL) {
182                 LOG(L_ERR, "parse_proxy_require(): Error while parsing\n");
183                 return -1;
184         }
185
186         _h->parsed = pr_l;
187         return 0;
188 }
189
190 /* check the SIP version in the request URI */
191 int check_ruri_sip_version(struct sip_msg* _msg) {
192         char *sep;
193         str version;
194
195 #ifdef EXTRA_DEBUG
196         DBG("check_ruri_sip_version entered\n");
197 #endif
198
199         if (_msg->first_line.u.request.version.len != 0) {
200                 sep = q_memchr(_msg->first_line.u.request.version.s, '/',
201                                                 _msg->first_line.u.request.version.len);
202                 if (sep == NULL) {
203                         LOG(L_WARN, "sanity_check(): check_ruri_sip_version():"
204                                         " failed to find / in ruri version\n");
205                         return SANITY_CHECK_FAILED;
206                 }
207                 version.s = sep + 1;
208                 version.len = _msg->first_line.u.request.version.len - (version.s - _msg->first_line.u.request.version.s);
209
210                 if (version.len != SIP_VERSION_TWO_POINT_ZERO_LENGTH ||
211                         (memcmp(version.s, SIP_VERSION_TWO_POINT_ZERO, 
212                                 SIP_VERSION_TWO_POINT_ZERO_LENGTH) != 0)) {
213                         if (_msg->REQ_METHOD != METHOD_ACK) {
214                                 if (sanity_reply(_msg, 505, "Version Not Supported (R-URI)")
215                                                 < 0) {
216                                         LOG(L_WARN, "sanity_check(): check_ruri_sip_version():"
217                                                         " failed to send 505 via sl reply\n");
218                                 }
219                         }
220 #ifdef EXTRA_DEBUG
221                         DBG("check_ruri_sip_version failed\n");
222 #endif
223                         return SANITY_CHECK_FAILED;
224                 }
225         }
226 #ifdef EXTRA_DEBUG
227         DBG("check_ruri_sip_version passed\n");
228 #endif
229         return SANITY_CHECK_PASSED;
230 }
231
232 /* check if the r-uri scheme */
233 int check_ruri_scheme(struct sip_msg* _msg) {
234
235 #ifdef EXTRA_DEBUG
236         DBG("check_ruri_scheme entered\n");
237 #endif
238
239         if (_msg->parsed_uri_ok == 0 &&
240                         parse_sip_msg_uri(_msg) != 1) {
241                 /* unsupported schemes end up here already */
242                 LM_WARN("failed to parse request uri [%.*s]\n",
243                                 GET_RURI(_msg)->len, GET_RURI(_msg)->s);
244         }
245         if (_msg->parsed_uri.type == ERROR_URI_T) {
246                 if (_msg->REQ_METHOD != METHOD_ACK) {
247                         if (sanity_reply(_msg, 416, "Unsupported URI Scheme in Request URI")
248                                         < 0) {
249                                 LOG(L_WARN, "sanity_check(): check_ruri_scheme():"
250                                                 " failed to send 416 via sl reply\n");
251                         }
252                 }
253                 DBG("check_ruri_scheme failed\n");
254                 return SANITY_CHECK_FAILED;
255         }
256 #ifdef EXTRA_DEBUG
257         DBG("check_ruri_scheme passed\n");
258 #endif
259
260         return SANITY_CHECK_PASSED;
261 }
262
263 /* check for the presence of the minimal required headers */
264 int check_required_headers(struct sip_msg* _msg) {
265
266 #ifdef EXTRA_DEBUG
267         DBG("check_required_headers entered\n");
268 #endif
269
270         if (!check_transaction_quadruple(_msg)) {
271                 if (_msg->REQ_METHOD != METHOD_ACK) {
272                         if (sanity_reply(_msg, 400, "Missing Required Header in Request")
273                                         < 0) {
274                                 LOG(L_WARN, "sanity_check(): check_required_headers():"
275                                                 " failed to send 400 via sl reply\n");
276                         }
277                 }
278                 DBG("check_required_headers failed\n");
279                 return SANITY_CHECK_FAILED;
280         }
281         /* TODO: check for other required headers according to request type */
282 #ifdef EXTRA_DEBUG
283         DBG("check_required_headers passed\n");
284 #endif
285
286         return SANITY_CHECK_PASSED;
287 }
288
289 /* check if the SIP version in the Via header is 2.0 */
290 int check_via_sip_version(struct sip_msg* _msg) {
291
292         DBG("sanity_check(): check_via_sip_version(): this is a useless check"
293                         " for now; check the source code comments for details\n");
294         return SANITY_CHECK_PASSED;
295
296         /* FIMXE the Via parser fails already on non-2.0 versions
297          * thus this check makes no sence yet
298         DBG("check_via_sip_version entered\n");
299
300         // FIXME via parser fails on non 2.0 number
301         if (parse_headers(_msg, HDR_VIA1_F, 0) != 0) {
302                 LOG(L_WARN, "sanity_check(): check_via_sip_version():"
303                         " failed to parse the first Via header\n");
304                 return SANITY_CHECK_FAILED;
305         }
306
307         if (_msg->via1->version.len != 3 ||
308                         memcmp(_msg->via1->version.s, SIP_VERSION_TWO_POINT_ZERO, 
309                                         SIP_VERSION_TWO_POINT_ZERO_LENGTH ) != 0) {
310                 if (_msg->REQ_METHOD != METHOD_ACK) {
311                         if (sanity_reply(_msg, 505, "Version Not Supported (Via)") < 0) {
312                                 LOG(L_WARN, "sanity_check(): check_via_sip_version():"
313                                         " failed to send 505 via sl reply\n");
314                         }
315                 }
316                 DBG("check_via_sip_version failed\n");
317                 return SANITY_CHECK_FAILED;
318         }
319 #ifdef EXTRA_DEBUG
320         DBG("check_via_sip_version passed\n");
321 #endif
322
323         return SANITY_CHECK_PASSED;
324         */
325 }
326
327 /* compare the protocol string in the Via header with the transport */
328 int check_via_protocol(struct sip_msg* _msg) {
329
330         DBG("sanity_check(): check_via_protocol(): this is a useless check"
331                         " for now; check the source code comment for details\n");
332         return SANITY_CHECK_PASSED;
333
334         /* FIXME as the Via parser fails already on unknown transports
335          * this function makes no sence yet
336         DBG("check_via_protocol entered\n");
337
338         // FIXME via parser fails on unknown transport
339         if (parse_headers(_msg, HDR_VIA1_F, 0) != 0) {
340                 LOG(L_WARN, "sanity_check(): check_via_protocol():"
341                         " failed to parse the first Via header\n");
342                 return SANITY_CHECK_FAILED;
343         }
344         if (_msg->via1->transport.len != 3 &&
345                         _msg->via1->transport.len != 4) {
346                 if (_msg->REQ_METHOD != METHOD_ACK) {
347                         if (sanity_reply(_msg, 400, "Unsupported Transport in Topmost Via")
348                                         < 0) {
349                                 LOG(L_WARN, "sanity_check(): check_via_protocol():"
350                                         " failed to send 400 via sl reply\n");
351                         }
352                 }
353                 DBG("check_via_protocol failed\n");
354                 return SANITY_CHECK_FAILED;
355         }
356         switch (_msg->rcv.proto) {
357                 case PROTO_UDP:
358                         if (memcmp(_msg->via1->transport.s, "UDP", 3) != 0) {
359                                 if (_msg->REQ_METHOD != METHOD_ACK) {
360                                         if (sanity_reply(_msg, 400,
361                                                         "Transport Missmatch in Topmost Via") < 0) {
362                                                 LOG(L_WARN, "sanity_check(): check_via_protocol():"
363                                                                 " failed to send 505 via sl reply\n");
364                                         }
365                                 }
366                                 DBG("check_via_protocol failed\n");
367                                 return SANITY_CHECK_FAILED;
368                         }
369                         break;
370                 case PROTO_TCP:
371                         if (memcmp(_msg->via1->transport.s, "TCP", 3) != 0) {
372                                 if (_msg->REQ_METHOD != METHOD_ACK) {
373                                         if (sanity_reply(_msg, 400,
374                                                         "Transport Missmatch in Topmost Via") < 0) {
375                                                 LOG(L_WARN, "sanity_check(): check_via_protocol():"
376                                                                 " failed to send 505 via sl reply\n");
377                                         }
378                                 }
379                                 DBG("check_via_protocol failed\n");
380                                 return SANITY_CHECK_FAILED;
381                         }
382                         break;
383                 case PROTO_TLS:
384                         if (memcmp(_msg->via1->transport.s, "TLS", 3) != 0) {
385                                 if (_msg->REQ_METHOD != METHOD_ACK) {
386                                         if (sanity_reply(_msg, 400,
387                                                         "Transport Missmatch in Topmost Via") < 0) {
388                                                 LOG(L_WARN, "sanity_check(): check_via_protocol():"
389                                                                 " failed to send 505 via sl reply\n");
390                                         }
391                                 }
392                                 DBG("check_via_protocol failed\n");
393                                 return SANITY_CHECK_FAILED;
394                         }
395                         break;
396                 case PROTO_SCTP:
397                         if (memcmp(_msg->via1->transport.s, "SCTP", 4) != 0) {
398                                 if (_msg->REQ_METHOD != METHOD_ACK) {
399                                         if (sanity_reply(_msg, 400,
400                                                         "Transport Missmatch in Topmost Via") < 0) {
401                                                 LOG(L_WARN, "sanity_check(): check_via_protocol():"
402                                                                 " failed to send 505 via sl reply\n");
403                                         }
404                                 }
405                                 DBG("check_via_protocol failed\n");
406                                 return SANITY_CHECK_FAILED;
407                         }
408                         break;
409                 default:
410                         LOG(L_WARN, "sanity_check(): check_via_protocol():"
411                                         " unknown protocol in received structure\n");
412                         return SANITY_CHECK_FAILED;
413         }
414 #ifdef EXTRA_DEBUG
415         DBG("check_via_protocol passed\n");
416 #endif
417
418         return SANITY_CHECK_PASSED;
419         */
420 }
421
422 /* compare the method in the CSeq header with the request line value */
423 int check_cseq_method(struct sip_msg* _msg) {
424
425 #ifdef EXTRA_DEBUG
426         DBG("check_cseq_method entered\n");
427 #endif
428
429         if (parse_headers(_msg, HDR_CSEQ_F, 0) != 0) {
430                 LOG(L_WARN, "sanity_check(): check_cseq_method():"
431                                 " failed to parse the CSeq header\n");
432                 return SANITY_CHECK_FAILED;
433         }
434         if (_msg->cseq != NULL && _msg->cseq->parsed != NULL) {
435                 if (((struct cseq_body*)_msg->cseq->parsed)->method.len == 0) {
436                         if (_msg->REQ_METHOD != METHOD_ACK) {
437                                 if (sanity_reply(_msg, 400, "Missing method in CSeq header")
438                                                 < 0) {
439                                         LOG(L_WARN, "sanity_check(): check_cseq_method():"
440                                                         " failed to send 400 via sl reply\n");
441                                 }
442                         }
443                         DBG("check_cseq_method failed (missing method)\n");
444                         return SANITY_CHECK_FAILED;
445                 }
446
447                 if (((struct cseq_body*)_msg->cseq->parsed)->method.len != 
448                                         _msg->first_line.u.request.method.len ||
449                         memcmp(((struct cseq_body*)_msg->cseq->parsed)->method.s, 
450                                 _msg->first_line.u.request.method.s,
451                                 ((struct cseq_body*)_msg->cseq->parsed)->method.len) != 0) {
452                         if (_msg->REQ_METHOD != METHOD_ACK) {
453                                 if (sanity_reply(_msg, 400,
454                                                         "CSeq method does not match request method") < 0) {
455                                         LOG(L_WARN, "sanity_check(): check_cseq_method():"
456                                                         " failed to send 400 via sl reply 2\n");
457                                 }
458                         }
459                         DBG("check_cseq_method failed (non-equal method)\n");
460                         return SANITY_CHECK_FAILED;
461                 }
462         }
463         else {
464                 LOG(L_WARN, "sanity_check(): check_cseq_method():"
465                                 " missing CSeq header\n");
466                 return SANITY_CHECK_FAILED;
467         }
468 #ifdef EXTRA_DEBUG
469         DBG("check_cseq_method passed\n");
470 #endif
471
472         return SANITY_CHECK_PASSED;
473 }
474
475 /* check the number within the CSeq header */
476 int check_cseq_value(struct sip_msg* _msg) {
477         unsigned int cseq;
478
479 #ifdef EXTRA_DEBUG
480         DBG("check_cseq_value entered\n");
481 #endif
482
483         if (parse_headers(_msg, HDR_CSEQ_F, 0) != 0) {
484                 LOG(L_WARN, "sanity_check(): check_cseq_value():"
485                                 " failed to parse the CSeq header\n");
486                 return SANITY_CHECK_FAILED;
487         }
488         if (_msg->cseq != NULL && _msg->cseq->parsed != NULL) {
489                 if (((struct cseq_body*)_msg->cseq->parsed)->number.len == 0) {
490                         if (_msg->REQ_METHOD != METHOD_ACK) {
491                                 if (sanity_reply(_msg, 400, "Missing number in CSeq header")
492                                                 < 0) {
493                                         LOG(L_WARN, "sanity_check(): check_cseq_value():"
494                                                         " failed to send 400 via sl reply\n");
495                                 }
496                         }
497                         return SANITY_CHECK_FAILED;
498                 }
499                 if (str2valid_uint(&((struct cseq_body*)_msg->cseq->parsed)->number,
500                                         &cseq) != 0) {
501                         if (_msg->REQ_METHOD != METHOD_ACK) {
502                                 if (sanity_reply(_msg, 400, "CSeq number is illegal") < 0) {
503                                         LOG(L_WARN, "sanity_check(): check_cseq_value():"
504                                                         " failed to send 400 via sl reply 2\n");
505                                 }
506                         }
507                         DBG("check_cseq_value failed\n");
508                         return SANITY_CHECK_FAILED;
509                 }
510         }
511         else {
512                 LOG(L_WARN, "sanity_check(): check_cseq_method():"
513                                 " missing CSeq header\n");
514                 return SANITY_CHECK_FAILED;
515         }
516 #ifdef EXTRA_DEBUG
517         DBG("check_cseq_value passed\n");
518 #endif
519
520         return SANITY_CHECK_PASSED;
521 }
522
523 /* compare the Content-Length value with the accutal body length */
524 int check_cl(struct sip_msg* _msg) {
525         char *body;
526
527 #ifdef EXTRA_DEBUG
528         DBG("check_cl entered\n");
529 #endif
530
531         if (parse_headers(_msg, HDR_CONTENTLENGTH_F, 0) != 0) {
532                 LOG(L_WARN, "sanity_check(): check_cl():"
533                                 " failed to parse content-length header\n");
534                 return SANITY_CHECK_FAILED;
535         }
536         if (_msg->content_length != NULL) {
537                 //dump_hdr_field(_msg->content_length);
538                 if ((body = get_body(_msg)) == NULL) {
539 #ifdef EXTRA_DEBUG
540                         DBG("check_cl(): no body\n");
541 #endif
542                         return SANITY_CHECK_FAILED;
543                 }
544                 if ((_msg->len - (body - _msg->buf)) != get_content_length(_msg)) {
545                         if (_msg->REQ_METHOD != METHOD_ACK) {
546                                 if (sanity_reply(_msg, 400, "Content-Length mis-match") < 0) {
547                                         LOG(L_WARN, "sanity_check(): check_cl():"
548                                                         " failed to send 400 via sl reply\n");
549                                 }
550                         }
551                         DBG("check_cl failed\n");
552                         return SANITY_CHECK_FAILED;
553                 }
554 #ifdef EXTRA_DEBUG
555                 DBG("check_cl passed\n");
556 #endif
557         }
558 #ifdef EXTRA_DEBUG
559         else {
560                 WARN("check_cl(): content length header missing in request\n");
561         }
562 #endif
563
564         return SANITY_CHECK_PASSED;
565 }
566
567 /* check the number within the Expires header */
568 int check_expires_value(struct sip_msg* _msg) {
569         unsigned int expires;
570
571 #ifdef EXTRA_DEBUG
572         DBG("check_expires_value entered\n");
573 #endif
574
575         if (parse_headers(_msg, HDR_EXPIRES_F, 0) != 0) {
576                 LOG(L_WARN, "sanity_check(): check_expires_value():"
577                                 " failed to parse expires header\n");
578                 return SANITY_CHECK_FAILED;
579         }
580         if (_msg->expires != NULL) {
581                 //dump_hdr_field(_msg->expires);
582                 if (_msg->expires->parsed == NULL &&
583                                 parse_expires(_msg->expires) < 0) {
584                         LOG(L_WARN, "sanity_check(): check_expires_value():"
585                                         " parse_expires failed\n");
586                         return SANITY_CHECK_FAILED;
587                 }
588                 if (((struct exp_body*)_msg->expires->parsed)->text.len == 0) {
589                         if (_msg->REQ_METHOD != METHOD_ACK) {
590                                 if (sanity_reply(_msg, 400, "Missing number in Expires header")
591                                                 < 0) {
592                                         LOG(L_WARN, "sanity_check(): check_expires_value():"
593                                                         " failed to send 400 via sl reply\n");
594                                 }
595                         }
596                         DBG("check_expires_value failed\n");
597                         return SANITY_CHECK_FAILED;
598                 }
599                 if (str2valid_uint(&((struct exp_body*)_msg->expires->parsed)->text, &expires) != 0) {
600                         if (_msg->REQ_METHOD != METHOD_ACK) {
601                                 if (sanity_reply(_msg, 400, "Expires value is illegal") < 0) {
602                                         LOG(L_WARN, "sanity_check(): check_expires_value():"
603                                                         " failed to send 400 via sl reply 2\n");
604                                 }
605                         }
606                         DBG("check_expires_value failed\n");
607                         return SANITY_CHECK_FAILED;
608                 }
609 #ifdef EXTRA_DEBUG
610                 DBG("check_expires_value passed\n");
611 #endif
612         }
613 #ifdef EXTRA_DEBUG
614         else {
615                 DBG("check_expires_value(): no expires header found\n");
616         }
617 #endif
618
619         return SANITY_CHECK_PASSED;
620 }
621
622 /* check the content of the Proxy-Require header */
623 int check_proxy_require(struct sip_msg* _msg) {
624         strl *r_pr, *l_pr;
625         char *u;
626         int u_len;
627
628 #ifdef EXTRA_DEBUG
629         DBG("check_proxy_require entered\n");
630 #endif
631
632         if (parse_headers(_msg, HDR_PROXYREQUIRE_F, 0) != 0) {
633                 LOG(L_WARN, "sanity_check(): check_proxy_require():"
634                                 " failed to parse proxy require header\n");
635                 return SANITY_CHECK_FAILED;
636         }
637         if (_msg->proxy_require != NULL) {
638                 dump_hdr_field(_msg->proxy_require);
639                 if (_msg->proxy_require->parsed == NULL &&
640                                 parse_proxyrequire(_msg->proxy_require) < 0) {
641                         LOG(L_WARN, "sanity_check(): check_proxy_require(): parse_proxy_require failed\n");
642                         return SANITY_CHECK_FAILED;
643                 }
644                 r_pr = _msg->proxy_require->parsed;
645                 while (r_pr != NULL) {
646                         l_pr = proxyrequire_list;
647                         while (l_pr != NULL) {
648 #ifdef EXTRA_DEBUG
649                                 DBG("check_proxy_require(): comparing r='%.*s' l='%.*s'\n",
650                                                 r_pr->string.len, r_pr->string.s, l_pr->string.len,
651                                                 l_pr->string.s);
652 #endif
653                                 if (l_pr->string.len == r_pr->string.len &&
654                                                 /* FIXME tokens are case in-sensitive */
655                                                 memcmp(l_pr->string.s, r_pr->string.s,
656                                                                 l_pr->string.len) == 0) {
657                                         break;
658                                 }
659                                 l_pr = l_pr->next;
660                         }
661                         if (l_pr == NULL) {
662                                 DBG("sanit_check(): check_proxy_require():"
663                                                 " request contains unsupported extension: %.*s\n",
664                                                 r_pr->string.len, r_pr->string.s);
665                                 u_len = UNSUPPORTED_HEADER_LEN + 2 + r_pr->string.len;
666                                 u = pkg_malloc(u_len);
667                                 if (u == NULL) {
668                                         LOG(L_ERR, "sanity_check(): check_proxy_require():"
669                                                         " failed to allocate memory for"
670                                                         " Unsupported header\n");
671                                 }
672                                 else {
673                                         memcpy(u, UNSUPPORTED_HEADER, UNSUPPORTED_HEADER_LEN);
674                                         memcpy(u + UNSUPPORTED_HEADER_LEN, r_pr->string.s,
675                                                         r_pr->string.len);
676                                         memcpy(u + UNSUPPORTED_HEADER_LEN + r_pr->string.len,
677                                                         CRLF, CRLF_LEN);
678                                         add_lump_rpl(_msg, u, u_len, LUMP_RPL_HDR);
679                                 }
680
681                                 if (_msg->REQ_METHOD != METHOD_ACK) {
682                                         if (sanity_reply(_msg, 420, "Bad Extension") < 0) {
683                                                 LOG(L_WARN, "sanity_check(): check_proxy_require():"
684                                                                 " failed to send 420 via sl reply\n");
685                                         }
686                                 }
687 #ifdef EXTRA_DEBUG
688                                 DBG("check_proxy_require failed\n");
689 #endif
690                                 if (u) pkg_free(u);
691                                 return SANITY_CHECK_FAILED;
692                         }
693                         else {
694                                 r_pr = r_pr->next;
695                         }
696                 }
697 #ifdef EXTRA_DEBUG
698                 DBG("check_proxy_require passed\n");
699 #endif
700                 if (_msg->proxy_require->parsed) {
701                         /* TODO we have to free it here, because it is not automatically
702                          * freed when the message freed. Lets hope nobody needs to access
703                          * this header again later on */
704                         free_str_list(_msg->proxy_require->parsed);
705                 }
706         }
707 #ifdef EXTRA_DEBUG
708         else {
709                 DBG("check_proxy_require(): no proxy-require header found\n");
710         }
711 #endif
712
713         return SANITY_CHECK_PASSED;
714 }
715
716 /* check if the typical URI's are parseable */
717 int check_parse_uris(struct sip_msg* _msg, int checks) {
718
719         struct to_body *ft_body = NULL;
720         struct sip_uri uri;
721
722 #ifdef EXTRA_DEBUG
723         DBG("check_parse_uris entered\n");
724 #endif
725
726         /* check R-URI */
727         if (SANITY_URI_CHECK_RURI & checks) {
728 #ifdef EXTRA_DEBUG
729                 DBG("check_parse_uris(): parsing ruri\n");
730 #endif
731                 if (_msg->parsed_uri_ok == 0 &&
732                                 parse_sip_msg_uri(_msg) != 1) {
733                         LOG(L_WARN, "sanity_check(): check_parse_uris():"
734                                         " failed to parse request uri\n");
735                         if (_msg->REQ_METHOD != METHOD_ACK) {
736                                 if (sanity_reply(_msg, 400, "Bad Request URI") < 0) {
737                                         LOG(L_WARN, "sanity_check(): check_parse_uris():"
738                                                         " failed to send 400 via sl reply (bad ruri)\n");
739                                 }
740                         }
741                         return SANITY_CHECK_FAILED;
742                 }
743                 /* FIXME: would it make sense to check here for "mandatory"
744                  * or "requested" parts of the URI? */
745         }
746         /* check From URI */
747         if (SANITY_URI_CHECK_FROM & checks) {
748 #ifdef EXTRA_DEBUG
749                 DBG("check_parse_uris(): looking up From header\n");
750 #endif
751                 if ((!_msg->from && parse_headers(_msg, HDR_FROM_F, 0) != 0)
752                                 || !_msg->from) {
753                         LOG(L_WARN, "sanity_check(): check_parse_uris():"
754                                         " missing from header\n");
755                         if (_msg->REQ_METHOD != METHOD_ACK) {
756                                 if (sanity_reply(_msg, 400, "Missing From Header") < 0) {
757                                         LOG(L_WARN, "sanity_check(): check_parse_uris():"
758                                                 " failed to send 400 via sl reply (missing From)\n");
759                                 }
760                         }
761                         return SANITY_CHECK_FAILED;
762                 }
763                 if (!_msg->from->parsed) {
764 #ifdef EXTRA_DEBUG
765                         DBG("check_parse_uris(): parsing From header\n");
766 #endif
767                         ft_body = pkg_malloc(sizeof(struct to_body));
768                         if (!ft_body) {
769                                 LOG(L_ERR, "sanity_check(): check_parse_uris():"
770                                                 " out of pkg_memory (From)\n");
771                                 return SANITY_CHECK_ERROR;
772                         }
773                         memset(ft_body, 0, sizeof(struct to_body));
774                         parse_to(_msg->from->body.s, _msg->from->body.s + \
775                                         _msg->from->body.len + 1, ft_body);
776                         if (ft_body->error == PARSE_ERROR) {
777                                 LOG(L_WARN, "sanity_check(): check_parse_uris():"
778                                                 " failed to parse From header [%.*s]\n",
779                                                 _msg->from->body.len, _msg->from->body.s);
780                                 free_to(ft_body);
781                                 if (_msg->REQ_METHOD != METHOD_ACK) {
782                                         if (sanity_reply(_msg, 400, "Bad From header") < 0) {
783                                                 LOG(L_WARN, "sanity_check(): check_parse_uris():"
784                                                                 " failed to send 400 via sl reply"
785                                                                 " (bad from header)\n");
786                                         }
787                                 }
788                                 return SANITY_CHECK_FAILED;
789                         }
790                         _msg->from->parsed = ft_body;
791                         ft_body = NULL;
792                 }
793                 if (((struct to_body*)_msg->from->parsed)->uri.s) {
794 #ifdef EXTRA_DEBUG
795                         DBG("check_parse_uris(): parsing From URI\n");
796 #endif
797                         if (parse_uri(((struct to_body*)_msg->from->parsed)->uri.s, 
798                                         ((struct to_body*)_msg->from->parsed)->uri.len, &uri) != 0) {
799                             LOG(L_WARN, "sanity_check(): check_parse_uris():"
800                                                 " failed to parse From uri\n");
801                             if (_msg->REQ_METHOD != METHOD_ACK) {
802                                 if (sanity_reply(_msg, 400, "Bad From URI") < 0) {
803                                     LOG(L_WARN, "sanity_check(): check_parse_uris():"
804                                                         " failed to send 400 via sl reply"
805                                                         " (bad from uri)\n");
806                                 }
807                             }
808                             return SANITY_CHECK_FAILED;
809                         }
810                         /* FIXME: we should store this parsed struct somewhere so that
811                          * it could be re-used */
812                         /* FIXME 2: would it make sense to check here for "mandatory"
813                          * or "requested" parts of the URI? */
814                 }
815         }
816         /* check To URI */
817         if (SANITY_URI_CHECK_TO & checks) {
818 #ifdef EXTRA_DEBUG
819                 DBG("check_parse_uris(): looking up To header\n");
820 #endif
821                 if ((!_msg->to && parse_headers(_msg, HDR_TO_F, 0) != 0)
822                                 || !_msg->to) {
823                         LOG(L_WARN, "sanity_check(): check_parse_uris():"
824                                         " missing to header\n");
825                         if (_msg->REQ_METHOD != METHOD_ACK) {
826                                 if (sanity_reply(_msg, 400, "Missing To Header") < 0) {
827                                         LOG(L_WARN, "sanity_check(): check_parse_uris():"
828                                                         " failed to send 400 via sl reply (missing To)\n");
829                                 }
830                         }
831                         return SANITY_CHECK_FAILED;
832                 }
833                 /* parse_to is automatically called for HDR_TO_F */
834                 if (!_msg->to->parsed) {
835                         LOG(L_WARN, "sanity_check(): check_parse_uris():"
836                                         " failed to parse To header\n");
837                         if (_msg->REQ_METHOD != METHOD_ACK) {
838                                 if (sanity_reply(_msg, 400, "Bad To URI") < 0) {
839                                         LOG(L_WARN, "sanity_check(): check_parse_uris():"
840                                                         " failed to send 400 via sl reply (bad to uri)\n");
841                                 }
842                         }
843                         return SANITY_CHECK_FAILED;
844                 }
845                 if (((struct to_body*)_msg->to->parsed)->uri.s) {
846 #ifdef EXTRA_DEBUG
847                         DBG("check_parse_uris(): parsing To URI\n");
848 #endif
849                         if (parse_uri(((struct to_body*)_msg->to->parsed)->uri.s, 
850                                         ((struct to_body*)_msg->to->parsed)->uri.len, &uri) != 0) {
851                                 LOG(L_WARN, "sanity_check(): check_parse_uris():"
852                                                 " failed to parse To uri\n");
853                                 if (_msg->REQ_METHOD != METHOD_ACK) {
854                                         if (sanity_reply(_msg, 400, "Bad To URI") < 0) {
855                                                 LOG(L_WARN, "sanity_check(): check_parse_uris():"
856                                                                 " failed to send 400 via sl reply"
857                                                                 " (bad to uri)\n");
858                                         }
859                                 }
860                                 return SANITY_CHECK_FAILED;
861                         }
862                         /* FIXME: we should store this parsed struct somewhere so that
863                          * it could be re-used */
864                         /* FIXME 2: would it make sense to check here for "mandatory"
865                          * or "requested" parts of the URI? */
866                 }
867         }
868         /* check Contact URI */
869         if (SANITY_URI_CHECK_CONTACT & checks) {
870 #ifdef EXTRA_DEBUG
871                 DBG("check_parse_uris(): looking up Contact header\n");
872 #endif
873                 if ((!_msg->contact && parse_headers(_msg, HDR_CONTACT_F, 0) != 0)
874                                 || !_msg->contact) {
875                         LOG(L_WARN, "sanity_check(): check_parse_uris():"
876                                         " missing contact header\n");
877                 }
878                 if (_msg->contact) {
879 #ifdef EXTRA_DEBUG
880                         DBG("check_parse_uris(): parsing Contact header\n");
881 #endif
882                         if (parse_contact(_msg->contact) < 0) {
883                                 LOG(L_WARN, "sanity_check(): check_parse_uris():"
884                                                 " failed to parse Contact header\n");
885                                 if (_msg->REQ_METHOD != METHOD_ACK) {
886                                         if (sanity_reply(_msg, 400, "Bad Contact Header") < 0) {
887                                                 LOG(L_WARN, "sanity_check(): check_parse_uris():"
888                                                                 " failed to send 400 via send_reply"
889                                                                 " (bad Contact)\n");
890                                         }
891                                 }
892                                 return SANITY_CHECK_FAILED;
893                         }
894                         if (parse_uri(
895                                 ((struct contact_body*)_msg->contact->parsed)->contacts->uri.s,
896                                 ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len,
897                                 &uri) != 0) {
898                                 LOG(L_WARN, "sanity_check(): check_parse_uris():"
899                                                 " failed to parse Contact uri\n");
900                                 if (_msg->REQ_METHOD != METHOD_ACK) {
901                                         if (sanity_reply(_msg, 400, "Bad Contact URI") < 0) {
902                                                 LOG(L_WARN, "sanity_check(): check_parse_uris():"
903                                                                 " failed to send 400 via send_reply"
904                                                                 " (bad Contact uri)\n");
905                                         }
906                                 }
907                                 return SANITY_CHECK_FAILED;
908                         }
909                 }
910         }
911
912 #ifdef EXTRA_DEBUG
913         DBG("check_parse_uris passed\n");
914 #endif
915         return SANITY_CHECK_PASSED;
916 }
917
918
919 /* Make sure that username attribute in all digest credentials
920  * instances has a meaningful value
921  */
922 int check_digest(struct sip_msg* msg, int checks)
923 {
924     struct hdr_field* ptr;
925     dig_cred_t* cred;
926     int ret;
927     int hf_type;
928
929     if (parse_headers(msg, HDR_EOH_F, 0) != 0) {
930         LOG(L_ERR, "sanity_check(): check_digest:"
931                         " failed to parse proxy require header\n");
932         return SANITY_CHECK_FAILED;
933     }
934
935     if (!msg->authorization && !msg->proxy_auth) {
936 #ifdef EXTRA_DEBUG
937         DBG("sanity_check(): check_digest: Nothing to check\n");
938 #endif
939         return SANITY_CHECK_PASSED;
940     }
941
942     if (msg->authorization) {
943         hf_type = HDR_AUTHORIZATION_T;
944         ptr = msg->authorization;
945     } else {
946         hf_type = HDR_PROXYAUTH_T;
947         ptr = msg->proxy_auth;
948     }
949     while(ptr) {
950         if ((ret = parse_credentials(ptr)) != 0) {
951             DBG("sanity_check(): check_digest: Cannot parse credentials: %d\n",
952                                 ret);
953             return SANITY_CHECK_FAILED;
954         }
955
956         cred = &((auth_body_t*)ptr->parsed)->digest;
957
958         if (check_dig_cred(cred) != E_DIG_OK) {
959 #ifdef EXTRA_DEBUG
960             DBG("sanity_check(): check_digest: Digest credentials malformed\n");
961 #endif
962             return SANITY_CHECK_FAILED;
963         }
964
965         if (cred->username.whole.len == 0) {
966 #ifdef EXTRA_DEBUG
967             DBG("sanity_check(): check_digest: Empty username\n");
968 #endif
969             return SANITY_CHECK_FAILED;
970         }
971         
972         if (cred->nonce.len == 0) {
973 #ifdef EXTRA_DEBUG
974             DBG("sanity_check(): check_digest: Empty nonce attribute\n");
975 #endif
976             return SANITY_CHECK_FAILED;
977         }
978
979         if (cred->response.len == 0) {
980 #ifdef EXTRA_DEBUG
981             DBG("sanity_check(): check_digest: Empty response attribute\n");
982 #endif
983             return SANITY_CHECK_FAILED;
984         }
985
986         do {
987             ptr = ptr->next;
988         } while(ptr && ptr->type != hf_type);
989
990         if (!ptr && hf_type == HDR_AUTHORIZATION_T) {
991             hf_type = HDR_PROXYAUTH_T;
992             ptr = msg->proxy_auth;
993         }
994     }
995
996     return SANITY_CHECK_PASSED;
997 }
998
999
1000 /* check for the presence of duplicate tag prameters in To/From headers */
1001 int check_duptags(sip_msg_t* _msg)
1002 {
1003         to_body_t *tb;
1004         to_param_t *tp;
1005         int n;
1006
1007         if(parse_from_header(_msg)<0 || parse_to_header(_msg)<0) {
1008                 DBG("check_duptags failed while parsing\n");
1009                 return SANITY_CHECK_FAILED;
1010         }
1011         tb = get_from(_msg);
1012         if(tb->tag_value.s!=NULL) {
1013                 n = 0;
1014                 for(tp = tb->param_lst; tp; tp = tp->next) {
1015                         if(tp->type==TAG_PARAM)
1016                                 n++;
1017                 }
1018                 if(n>1) {
1019                         DBG("check_duptags failed for From header\n");
1020                         return SANITY_CHECK_FAILED;
1021                 }
1022         }
1023         tb = get_to(_msg);
1024         if(tb->tag_value.s!=NULL) {
1025                 n = 0;
1026                 for(tp = tb->param_lst; tp; tp = tp->next) {
1027                         if(tp->type==TAG_PARAM)
1028                                 n++;
1029                 }
1030                 if(n>1) {
1031                         DBG("check_duptags failed for To header\n");
1032                         return SANITY_CHECK_FAILED;
1033                 }
1034         }
1035
1036         return SANITY_CHECK_PASSED;
1037 }
1038
1039