Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

sanity.c

Go to the documentation of this file.
00001 /*
00002  * $Id: sanity.c,v 1.11 2007/12/05 22:46:04 calrissian Exp $
00003  *
00004  * Sanity Checks Module
00005  *
00006  * Copyright (C) 2006 iptelorg GbmH
00007  *
00008  * This file is part of ser, a free SIP server.
00009  *
00010  * ser is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * For a license to use the ser software under conditions
00016  * other than those described here, or to purchase support for this
00017  * software, please contact iptel.org by e-mail at the following addresses:
00018  *    info@iptel.org
00019  *
00020  * ser is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License
00026  * along with this program; if not, write to the Free Software
00027  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  *
00029  */
00030 
00031 #include "mod_sanity.h"
00032 #include "sanity.h"
00033 #include "../../ut.h"
00034 #include "../../trim.h"
00035 #include "../../data_lump_rpl.h"
00036 #include "../../mem/mem.h"
00037 #include "../../parser/parse_uri.h"
00038 #include "../../parser/parse_expires.h"
00039 #include "../../parser/parse_content.h"
00040 #include "../../parser/digest/digest.h"
00041 #include "../../parser/contact/parse_contact.h"
00042 
00043 #define UNSUPPORTED_HEADER "Unsupported: "
00044 #define UNSUPPORTED_HEADER_LEN (sizeof(UNSUPPORTED_HEADER)-1)
00045 
00046 /* check if the given string is a valid unsigned int value */
00047 int str2valid_uint(str* _number, unsigned int* _result) {
00048         int i;
00049         int result= 0;
00050         int equal = 1;
00051         char mui[10] = "4294967296";
00052 
00053         *_result = 0;
00054         if (_number->len > 10) {
00055 #ifdef EXTRA_DEBUG
00056                 DBG("valid_uint(): number is too long\n");
00057 #endif
00058                 return -1;
00059         }
00060         if (_number->len < 10) {
00061                 equal = 0;
00062         }
00063         for (i=0; i < _number->len; i++) {
00064                 if (_number->s[i] < '0' || _number->s[i] > '9') {
00065 #ifdef EXTRA_DEBUG
00066                         DBG("valid_uint(): number contains non-number char\n");
00067 #endif
00068                         return -1;
00069                 }
00070                 if (equal == 1) {
00071                         if (_number->s[i] < mui[i]) {
00072                                 equal = 0;
00073                         }
00074                         else if (_number->s[i] > mui[i]) {
00075 #ifdef EXTRA_DEBUG
00076                                 DBG("valid_uint(): number exceeds uint\n");
00077 #endif
00078                                 return -1;
00079                         }
00080                 }
00081                 result *= 10;
00082                 result += _number->s[i] - '0';
00083         }
00084         *_result = result;
00085         return 0;
00086 }
00087 
00088 /* parses the given comma seperated string into a string list */
00089 strl* parse_str_list(str* _string) {
00090         str input;
00091         strl *parsed_list, *pl;
00092         char *comma;
00093 
00094         /* make a copy because we trim it */
00095         input.s = _string->s;
00096         input.len = _string->len;
00097 
00098         trim(&input);
00099 
00100         if (input.len == 0) {
00101 #ifdef EXTRA_DEBUG
00102                 DBG("parse_str_list: list is empty\n");
00103 #endif
00104                 return NULL;
00105         }
00106         parsed_list = pkg_malloc(sizeof(strl));
00107         if (parsed_list == NULL) {
00108                 LOG(L_ERR, "parse_str_list: OUT OF MEMORY for initial list element\n");
00109                 return NULL;
00110         }
00111         memset(parsed_list, 0, sizeof(strl));
00112         parsed_list->string.s = input.s;
00113         parsed_list->string.len = input.len;
00114 
00115         comma = q_memchr(input.s, ',', input.len);
00116         pl = parsed_list;
00117         while (comma != NULL) {
00118                 pl->next = pkg_malloc(sizeof(strl));
00119                 if (pl->next == NULL) {
00120                         LOG(L_ERR, "parse_str_list: OUT OF MEMORY for further list element\n");
00121                         return parsed_list;
00122                 }
00123                 memset(pl->next, 0, sizeof(strl));
00124                 pl->next->string.s = comma + 1;
00125                 pl->next->string.len = pl->string.len - (pl->next->string.s - pl->string.s);
00126                 pl->string.len = comma - pl->string.s;
00127                 trim_trailing(&(pl->string));
00128                 pl = pl->next;
00129                 trim_leading(&(pl->string));
00130                 comma = q_memchr(pl->string.s, ',', pl->string.len);
00131         }
00132 
00133         return parsed_list;
00134 }
00135 
00136 /* free the elements of the linked str list */
00137 void free_str_list(strl *_list) {
00138         strl *cur, *next;
00139 
00140         if (_list != NULL) {
00141                 cur = _list;
00142                 while (cur != NULL) {
00143                         next = cur->next;
00144                         pkg_free(cur);
00145                         cur = next;
00146                 }
00147         }
00148 }
00149 
00150 int parse_proxyrequire(struct hdr_field* _h) {
00151         strl *pr_l;
00152 
00153         if (_h->parsed) {
00154                 return 0; /* Already parsed */
00155         }
00156 
00157         if ((pr_l = parse_str_list(&(_h->body))) == NULL) {
00158                 LOG(L_ERR, "parse_proxy_require(): Error while parsing\n");
00159                 return -1;
00160         }
00161 
00162         _h->parsed = pr_l;
00163         return 0;
00164 }
00165 
00166 /* check the SIP version in the request URI */
00167 int check_ruri_sip_version(struct sip_msg* _msg) {
00168         char *sep;
00169         str version;
00170 
00171 #ifdef EXTRA_DEBUG
00172         DBG("check_ruri_sip_version entered\n");
00173 #endif
00174 
00175         if (_msg->first_line.u.request.version.len != 0) {
00176                 sep = q_memchr(_msg->first_line.u.request.version.s, '/',
00177                                                 _msg->first_line.u.request.version.len);
00178                 if (sep == NULL) {
00179                         LOG(L_WARN, "sanity_check(): check_ruri_sip_version(): failed to find / in ruri version\n");
00180                         return SANITY_CHECK_FAILED;
00181                 }
00182                 version.s = sep + 1;
00183                 version.len = _msg->first_line.u.request.version.len - (version.s - _msg->first_line.u.request.version.s);
00184 
00185                 if (version.len != SIP_VERSION_TWO_POINT_ZERO_LENGTH ||
00186                         (memcmp(version.s, SIP_VERSION_TWO_POINT_ZERO, 
00187                                 SIP_VERSION_TWO_POINT_ZERO_LENGTH) != 0)) {
00188                         if (_msg->REQ_METHOD != METHOD_ACK) {
00189                                 if (sl.reply(_msg, 505, "Version Not Supported (R-URI)") == -1) {
00190                                         LOG(L_WARN, "sanity_check(): check_ruri_sip_version(): failed to send 505 via send_reply\n");
00191                                 }
00192                         }
00193 #ifdef EXTRA_DEBUG
00194                         DBG("check_ruri_sip_version failed\n");
00195 #endif
00196                         return SANITY_CHECK_FAILED;
00197                 }
00198         }
00199 #ifdef EXTRA_DEBUG
00200         DBG("check_ruri_sip_version passed\n");
00201 #endif
00202         return SANITY_CHECK_PASSED;
00203 }
00204 
00205 /* check if the r-uri scheme */
00206 int check_ruri_scheme(struct sip_msg* _msg) {
00207 
00208 #ifdef EXTRA_DEBUG
00209         DBG("check_ruri_scheme entered\n");
00210 #endif
00211 
00212         if (_msg->parsed_uri_ok == 0 &&
00213                         parse_sip_msg_uri(_msg) != 1) {
00214                 /* unsupported schemes end up here already */
00215                 LOG(L_WARN, "sanity_check(): check_ruri_scheme(): failed to parse request uri\n");
00216         }
00217         if (_msg->parsed_uri.type == ERROR_URI_T) {
00218                 if (_msg->REQ_METHOD != METHOD_ACK) {
00219                         if (sl.reply(_msg, 416, "Unsupported URI Scheme in Request URI") == -1) {
00220                                 LOG(L_WARN, "sanity_check(): check_ruri_scheme(): failed to send 416 via send_reply\n");
00221                         }
00222                 }
00223                 DBG("check_ruri_scheme failed\n");
00224                 return SANITY_CHECK_FAILED;
00225         }
00226 #ifdef EXTRA_DEBUG
00227         DBG("check_ruri_scheme passed\n");
00228 #endif
00229 
00230         return SANITY_CHECK_PASSED;
00231 }
00232 
00233 /* check for the presence of the minimal required headers */
00234 int check_required_headers(struct sip_msg* _msg) {
00235 
00236 #ifdef EXTRA_DEBUG
00237         DBG("check_required_headers entered\n");
00238 #endif
00239 
00240         if (!check_transaction_quadruple(_msg)) {
00241                 if (_msg->REQ_METHOD != METHOD_ACK) {
00242                         if (sl.reply(_msg, 400, "Missing Required Header in Request") == -1) {
00243                                 LOG(L_WARN, "sanity_check(): check_required_headers(): failed to send 400 via send_reply\n");
00244                         }
00245                 }
00246                 DBG("check_required_headers failed\n");
00247                 return SANITY_CHECK_FAILED;
00248         }
00249         /* TODO: check for other required headers according to request type */
00250 #ifdef EXTRA_DEBUG
00251         DBG("check_required_headers passed\n");
00252 #endif
00253 
00254         return SANITY_CHECK_PASSED;
00255 }
00256 
00257 /* check if the SIP version in the Via header is 2.0 */
00258 int check_via_sip_version(struct sip_msg* _msg) {
00259 
00260         DBG("sanity_check(): check_via_sip_version(): this is a useless check for now; check the source code comments for details\n");
00261         return SANITY_CHECK_PASSED;
00262 
00263         /* FIMXE the Via parser fails already on non-2.0 versions
00264          * thus this check makes no sence yet
00265         DBG("check_via_sip_version entered\n");
00266 
00267         // FIXME via parser fails on non 2.0 number
00268         if (parse_headers(_msg, HDR_VIA1_F, 0) != 0) {
00269                 LOG(L_WARN, "sanity_check(): check_via_sip_version(): failed to parse the first Via header\n");
00270                 return SANITY_CHECK_FAILED;
00271         }
00272 
00273         if (_msg->via1->version.len != 3 ||
00274                         memcmp(_msg->via1->version.s, SIP_VERSION_TWO_POINT_ZERO, 
00275                                         SIP_VERSION_TWO_POINT_ZERO_LENGTH ) != 0) {
00276                 if (_msg->REQ_METHOD != METHOD_ACK) {
00277                         if (sl.reply(_msg, 505, "Version Not Supported (Via)") == -1) {
00278                                 LOG(L_WARN, "sanity_check(): check_via_sip_version(): failed to send 505 via send_reply\n");
00279                         }
00280                 }
00281                 DBG("check_via_sip_version failed\n");
00282                 return SANITY_CHECK_FAILED;
00283         }
00284 #ifdef EXTRA_DEBUG
00285         DBG("check_via_sip_version passed\n");
00286 #endif
00287 
00288         return SANITY_CHECK_PASSED;
00289         */
00290 }
00291 
00292 /* compare the protocol string in the Via header with the transport */
00293 int check_via_protocol(struct sip_msg* _msg) {
00294 
00295         DBG("sanity_check(): check_via_protocol(): this is a useless check for now; check the source code comment for details\n");
00296         return SANITY_CHECK_PASSED;
00297 
00298         /* FIXME as the Via parser fails already on unknown transports
00299          * this function makes no sence yet
00300         DBG("check_via_protocol entered\n");
00301 
00302         // FIXME via parser fails on unknown transport
00303         if (parse_headers(_msg, HDR_VIA1_F, 0) != 0) {
00304                 LOG(L_WARN, "sanity_check(): check_via_protocol(): failed to parse the first Via header\n");
00305                 return SANITY_CHECK_FAILED;
00306         }
00307         if (_msg->via1->transport.len != 3 &&
00308                         _msg->via1->transport.len != 4) {
00309                 if (_msg->REQ_METHOD != METHOD_ACK) {
00310                         if (sl.reply(_msg, 400, "Unsupported Transport in Topmost Via") == -1) {
00311                                 LOG(L_WARN, "sanity_check(): check_via_protocol(): failed to send 400 via send_reply\n");
00312                         }
00313                 }
00314                 DBG("check_via_protocol failed\n");
00315                 return SANITY_CHECK_FAILED;
00316         }
00317         switch (_msg->rcv.proto) {
00318                 case PROTO_UDP:
00319                         if (memcmp(_msg->via1->transport.s, "UDP", 3) != 0) {
00320                                 if (_msg->REQ_METHOD != METHOD_ACK) {
00321                                         if (sl.reply(_msg, 400, "Transport Missmatch in Topmost Via") == -1) {
00322                                                 LOG(L_WARN, "sanity_check(): check_via_protocol(): failed to send 505 via send_reply\n");
00323                                         }
00324                                 }
00325                                 DBG("check_via_protocol failed\n");
00326                                 return SANITY_CHECK_FAILED;
00327                         }
00328                         break;
00329                 case PROTO_TCP:
00330                         if (memcmp(_msg->via1->transport.s, "TCP", 3) != 0) {
00331                                 if (_msg->REQ_METHOD != METHOD_ACK) {
00332                                         if (sl.reply(_msg, 400, "Transport Missmatch in Topmost Via") == -1) {
00333                                                 LOG(L_WARN, "sanity_check(): check_via_protocol(): failed to send 505 via send_reply\n");
00334                                         }
00335                                 }
00336                                 DBG("check_via_protocol failed\n");
00337                                 return SANITY_CHECK_FAILED;
00338                         }
00339                         break;
00340                 case PROTO_TLS:
00341                         if (memcmp(_msg->via1->transport.s, "TLS", 3) != 0) {
00342                                 if (_msg->REQ_METHOD != METHOD_ACK) {
00343                                         if (sl.reply(_msg, 400, "Transport Missmatch in Topmost Via") == -1) {
00344                                                 LOG(L_WARN, "sanity_check(): check_via_protocol(): failed to send 505 via send_reply\n");
00345                                         }
00346                                 }
00347                                 DBG("check_via_protocol failed\n");
00348                                 return SANITY_CHECK_FAILED;
00349                         }
00350                         break;
00351                 case PROTO_SCTP:
00352                         if (memcmp(_msg->via1->transport.s, "SCTP", 4) != 0) {
00353                                 if (_msg->REQ_METHOD != METHOD_ACK) {
00354                                         if (sl.reply(_msg, 400, "Transport Missmatch in Topmost Via") == -1) {
00355                                                 LOG(L_WARN, "sanity_check(): check_via_protocol(): failed to send 505 via send_reply\n");
00356                                         }
00357                                 }
00358                                 DBG("check_via_protocol failed\n");
00359                                 return SANITY_CHECK_FAILED;
00360                         }
00361                         break;
00362                 default:
00363                         LOG(L_WARN, "sanity_check(): check_via_protocol(): unknown protocol in received structure\n");
00364                         return SANITY_CHECK_FAILED;
00365         }
00366 #ifdef EXTRA_DEBUG
00367         DBG("check_via_protocol passed\n");
00368 #endif
00369 
00370         return SANITY_CHECK_PASSED;
00371         */
00372 }
00373 
00374 /* compare the method in the CSeq header with the request line value */
00375 int check_cseq_method(struct sip_msg* _msg) {
00376 
00377 #ifdef EXTRA_DEBUG
00378         DBG("check_cseq_method entered\n");
00379 #endif
00380 
00381         if (parse_headers(_msg, HDR_CSEQ_F, 0) != 0) {
00382                 LOG(L_WARN, "sanity_check(): check_cseq_method(): failed to parse the CSeq header\n");
00383                 return SANITY_CHECK_FAILED;
00384         }
00385         if (_msg->cseq != NULL && _msg->cseq->parsed != NULL) {
00386                 if (((struct cseq_body*)_msg->cseq->parsed)->method.len == 0) {
00387                         if (_msg->REQ_METHOD != METHOD_ACK) {
00388                                 if (sl.reply(_msg, 400, "Missing method in CSeq header") == -1) {
00389                                         LOG(L_WARN, "sanity_check(): check_cseq_method(): failed to send 400 via send_reply\n");
00390                                 }
00391                         }
00392                         DBG("check_cseq_method failed (missing method)\n");
00393                         return SANITY_CHECK_FAILED;
00394                 }
00395 
00396                 if (((struct cseq_body*)_msg->cseq->parsed)->method.len != 
00397                                         _msg->first_line.u.request.method.len ||
00398                         memcmp(((struct cseq_body*)_msg->cseq->parsed)->method.s, 
00399                                 _msg->first_line.u.request.method.s,
00400                                 ((struct cseq_body*)_msg->cseq->parsed)->method.len) != 0) {
00401                         if (_msg->REQ_METHOD != METHOD_ACK) {
00402                                 if (sl.reply(_msg, 400, "CSeq method does not match request method") == -1) {
00403                                         LOG(L_WARN, "sanity_check(): check_cseq_method(): failed to send 400 via send_reply 2\n");
00404                                 }
00405                         }
00406                         DBG("check_cseq_method failed (non-equal method)\n");
00407                         return SANITY_CHECK_FAILED;
00408                 }
00409         }
00410         else {
00411                 LOG(L_WARN, "sanity_check(): check_cseq_method(): missing CSeq header\n");
00412                 return SANITY_CHECK_FAILED;
00413         }
00414 #ifdef EXTRA_DEBUG
00415         DBG("check_cseq_method passed\n");
00416 #endif
00417 
00418         return SANITY_CHECK_PASSED;
00419 }
00420 
00421 /* check the number within the CSeq header */
00422 int check_cseq_value(struct sip_msg* _msg) {
00423         unsigned int cseq;
00424 
00425 #ifdef EXTRA_DEBUG
00426         DBG("check_cseq_value entered\n");
00427 #endif
00428 
00429         if (parse_headers(_msg, HDR_CSEQ_F, 0) != 0) {
00430                 LOG(L_WARN, "sanity_check(): check_cseq_value(): failed to parse the CSeq header\n");
00431                 return SANITY_CHECK_FAILED;
00432         }
00433         if (_msg->cseq != NULL && _msg->cseq->parsed != NULL) {
00434                 if (((struct cseq_body*)_msg->cseq->parsed)->number.len == 0) {
00435                         if (_msg->REQ_METHOD != METHOD_ACK) {
00436                                 if (sl.reply(_msg, 400, "Missing number in CSeq header") == -1) {
00437                                         LOG(L_WARN, "sanity_check(): check_cseq_value(): failed to send 400 via send_reply\n");
00438                                 }
00439                         }
00440                         return SANITY_CHECK_FAILED;
00441                 }
00442                 if (str2valid_uint(&((struct cseq_body*)_msg->cseq->parsed)->number, &cseq) != 0) {
00443                         if (_msg->REQ_METHOD != METHOD_ACK) {
00444                                 if (sl.reply(_msg, 400, "CSeq number is illegal") == -1) {
00445                                         LOG(L_WARN, "sanity_check(): check_cseq_value(): failed to send 400 via send_reply 2\n");
00446                                 }
00447                         }
00448                         DBG("check_cseq_value failed\n");
00449                         return SANITY_CHECK_FAILED;
00450                 }
00451         }
00452         else {
00453                 LOG(L_WARN, "sanity_check(): check_cseq_method(): missing CSeq header\n");
00454                 return SANITY_CHECK_FAILED;
00455         }
00456 #ifdef EXTRA_DEBUG
00457         DBG("check_cseq_value passed\n");
00458 #endif
00459 
00460         return SANITY_CHECK_PASSED;
00461 }
00462 
00463 /* compare the Content-Length value with the accutal body length */
00464 int check_cl(struct sip_msg* _msg) {
00465         char *body;
00466 
00467 #ifdef EXTRA_DEBUG
00468         DBG("check_cl entered\n");
00469 #endif
00470 
00471         if (parse_headers(_msg, HDR_CONTENTLENGTH_F, 0) != 0) {
00472                 LOG(L_WARN, "sanity_check(): check_cl(): failed to parse content-length header\n");
00473                 return SANITY_CHECK_FAILED;
00474         }
00475         if (_msg->content_length != NULL) {
00476                 //dump_hdr_field(_msg->content_length);
00477                 if ((body = get_body(_msg)) == NULL) {
00478 #ifdef EXTRA_DEBUG
00479                         DBG("check_cl(): no body\n");
00480 #endif
00481                         return SANITY_CHECK_FAILED;
00482                 }
00483                 if ((_msg->len - (body - _msg->buf)) != get_content_length(_msg)) {
00484                         if (_msg->REQ_METHOD != METHOD_ACK) {
00485                                 if (sl.reply(_msg, 400, "Content-Length mis-match") == -1) {
00486                                         LOG(L_WARN, "sanity_check(): check_cl(): failed to send 400 via send_reply\n");
00487                                 }
00488                         }
00489                         DBG("check_cl failed\n");
00490                         return SANITY_CHECK_FAILED;
00491                 }
00492 #ifdef EXTRA_DEBUG
00493                 DBG("check_cl passed\n");
00494 #endif
00495         }
00496 #ifdef EXTRA_DEBUG
00497         else {
00498                 WARN("check_cl(): content length header missing in request\n");
00499         }
00500 #endif
00501 
00502         return SANITY_CHECK_PASSED;
00503 }
00504 
00505 /* check the number within the Expires header */
00506 int check_expires_value(struct sip_msg* _msg) {
00507         unsigned int expires;
00508 
00509 #ifdef EXTRA_DEBUG
00510         DBG("check_expires_value entered\n");
00511 #endif
00512 
00513         if (parse_headers(_msg, HDR_EXPIRES_F, 0) != 0) {
00514                 LOG(L_WARN, "sanity_check(): check_expires_value(): failed to parse expires header\n");
00515                 return SANITY_CHECK_FAILED;
00516         }
00517         if (_msg->expires != NULL) {
00518                 //dump_hdr_field(_msg->expires);
00519                 if (_msg->expires->parsed == NULL &&
00520                                 parse_expires(_msg->expires) < 0) {
00521                         LOG(L_WARN, "sanity_check(): check_expires_value(): parse_expires failed\n");
00522                         return SANITY_CHECK_FAILED;
00523                 }
00524                 if (((struct exp_body*)_msg->expires->parsed)->text.len == 0) {
00525                         if (_msg->REQ_METHOD != METHOD_ACK) {
00526                                 if (sl.reply(_msg, 400, "Missing number in Expires header") == -1) {
00527                                         LOG(L_WARN, "sanity_check(): check_expires_value(): failed to send 400 via send_reply\n");
00528                                 }
00529                         }
00530                         DBG("check_expires_value failed\n");
00531                         return SANITY_CHECK_FAILED;
00532                 }
00533                 if (str2valid_uint(&((struct exp_body*)_msg->expires->parsed)->text, &expires) != 0) {
00534                         if (_msg->REQ_METHOD != METHOD_ACK) {
00535                                 if (sl.reply(_msg, 400, "Expires value is illegal") == -1) {
00536                                         LOG(L_WARN, "sanity_check(): check_expires_value(): failed to send 400 via send_reply 2\n");
00537                                 }
00538                         }
00539                         DBG("check_expires_value failed\n");
00540                         return SANITY_CHECK_FAILED;
00541                 }
00542 #ifdef EXTRA_DEBUG
00543                 DBG("check_expires_value passed\n");
00544 #endif
00545         }
00546 #ifdef EXTRA_DEBUG
00547         else {
00548                 DBG("check_expires_value(): no expires header found\n");
00549         }
00550 #endif
00551 
00552         return SANITY_CHECK_PASSED;
00553 }
00554 
00555 /* check the content of the Proxy-Require header */
00556 int check_proxy_require(struct sip_msg* _msg) {
00557         strl *r_pr, *l_pr;
00558         char *u;
00559         int u_len;
00560 
00561 #ifdef EXTRA_DEBUG
00562         DBG("check_proxy_require entered\n");
00563 #endif
00564 
00565         if (parse_headers(_msg, HDR_PROXYREQUIRE_F, 0) != 0) {
00566                 LOG(L_WARN, "sanity_check(): check_proxy_require(): failed to parse proxy require header\n");
00567                 return SANITY_CHECK_FAILED;
00568         }
00569         if (_msg->proxy_require != NULL) {
00570                 dump_hdr_field(_msg->proxy_require);
00571                 if (_msg->proxy_require->parsed == NULL &&
00572                                 parse_proxyrequire(_msg->proxy_require) < 0) {
00573                         LOG(L_WARN, "sanity_check(): check_proxy_require(): parse_proxy_require failed\n");
00574                         return SANITY_CHECK_FAILED;
00575                 }
00576                 r_pr = _msg->proxy_require->parsed;
00577                 while (r_pr != NULL) {
00578                         l_pr = proxyrequire_list;
00579                         while (l_pr != NULL) {
00580 #ifdef EXTRA_DEBUG
00581                                 DBG("check_proxy_require(): comparing r='%.*s' l='%.*s'\n", r_pr->string.len, r_pr->string.s, l_pr->string.len, l_pr->string.s);
00582 #endif
00583                                 if (l_pr->string.len == r_pr->string.len &&
00584                                                 /* FIXME tokens are case in-sensitive */
00585                                                 memcmp(l_pr->string.s, r_pr->string.s, l_pr->string.len) == 0) {
00586                                         break;
00587                                 }
00588                                 l_pr = l_pr->next;
00589                         }
00590                         if (l_pr == NULL) {
00591                                 DBG("sanit_check(): check_proxy_require(): request contains unsupported extension: %.*s\n", r_pr->string.len, r_pr->string.s);
00592                                 u_len = UNSUPPORTED_HEADER_LEN + 2 + r_pr->string.len;
00593                                 u = pkg_malloc(u_len);
00594                                 if (u == NULL) {
00595                                         LOG(L_ERR, "sanity_check(): check_proxy_require(): failed to allocate memory for Unsupported header\n");
00596                                 }
00597                                 else {
00598                                         memcpy(u, UNSUPPORTED_HEADER, UNSUPPORTED_HEADER_LEN);
00599                                         memcpy(u + UNSUPPORTED_HEADER_LEN, r_pr->string.s, r_pr->string.len);
00600                                         memcpy(u + UNSUPPORTED_HEADER_LEN + r_pr->string.len, CRLF, CRLF_LEN);
00601                                         add_lump_rpl(_msg, u, u_len, LUMP_RPL_HDR);
00602                                 }
00603 
00604                                 if (_msg->REQ_METHOD != METHOD_ACK) {
00605                                         if (sl.reply(_msg, 420, "Bad Extension") == -1) {
00606                                                 LOG(L_WARN, "sanity_check(): check_proxy_require(): failed to send 420 via send_reply\n");
00607                                         }
00608                                 }
00609 #ifdef EXTRA_DEBUG
00610                                 DBG("check_proxy_require failed\n");
00611 #endif
00612                                 if (u) pkg_free(u);
00613                                 return SANITY_CHECK_FAILED;
00614                         }
00615                         else {
00616                                 r_pr = r_pr->next;
00617                         }
00618                 }
00619 #ifdef EXTRA_DEBUG
00620                 DBG("check_proxy_require passed\n");
00621 #endif
00622                 if (_msg->proxy_require->parsed) {
00623                         /* TODO we have to free it here, because it is not automatically
00624                          * freed when the message freed. Lets hope nobody needs to access
00625                          * this header again later on */
00626                         free_str_list(_msg->proxy_require->parsed);
00627                 }
00628         }
00629 #ifdef EXTRA_DEBUG
00630         else {
00631                 DBG("check_proxy_require(): no proxy-require header found\n");
00632         }
00633 #endif
00634 
00635         return SANITY_CHECK_PASSED;
00636 }
00637 
00638 /* check if the typical URI's are parseable */
00639 int check_parse_uris(struct sip_msg* _msg, int checks) {
00640 
00641         struct to_body *ft_body = NULL;
00642         struct sip_uri uri;
00643 
00644 #ifdef EXTRA_DEBUG
00645         DBG("check_parse_uris entered\n");
00646 #endif
00647 
00648         /* check R-URI */
00649         if (SANITY_URI_CHECK_RURI & checks) {
00650 #ifdef EXTRA_DEBUG
00651                 DBG("check_parse_uris(): parsing ruri\n");
00652 #endif
00653                 if (_msg->parsed_uri_ok == 0 &&
00654                                 parse_sip_msg_uri(_msg) != 1) {
00655                         LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to parse request uri\n");
00656                         if (_msg->REQ_METHOD != METHOD_ACK) {
00657                                 if (sl.reply(_msg, 400, "Bad Request URI") == -1) {
00658                                         LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to send 400 via send_reply (bad ruri)\n");
00659                                 }
00660                         }
00661                         return SANITY_CHECK_FAILED;
00662                 }
00663                 /* FIXME: would it make sense to check here for "mandatory"
00664                  * or "requested" parts of the URI? */
00665         }
00666         /* check From URI */
00667         if (SANITY_URI_CHECK_FROM & checks) {
00668 #ifdef EXTRA_DEBUG
00669                 DBG("check_parse_uris(): looking up From header\n");
00670 #endif
00671                 if ((!_msg->from && parse_headers(_msg, HDR_FROM_F, 0) != 0) || !_msg->from) {
00672                         LOG(L_WARN, "sanity_check(): check_parse_uris(): missing from header\n");
00673                         if (_msg->REQ_METHOD != METHOD_ACK) {
00674                                 if (sl.reply(_msg, 400, "Missing From Header") == -1) {
00675                                         LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to send 400 via send_reply (missing From)\n");
00676                                 }
00677                         }
00678                         return SANITY_CHECK_FAILED;
00679                 }
00680                 if (!_msg->from->parsed) {
00681 #ifdef EXTRA_DEBUG
00682                         DBG("check_parse_uris(): parsing From header\n");
00683 #endif
00684                         ft_body = pkg_malloc(sizeof(struct to_body));
00685                         if (!ft_body) {
00686                                 LOG(L_ERR, "sanity_check(): check_parse_uris(): out of pkg_memory (From)\n");
00687                                 return SANITY_CHECK_ERROR;
00688                         }
00689                         memset(ft_body, 0, sizeof(struct to_body));
00690                         parse_to(_msg->from->body.s, _msg->from->body.s + \
00691                                         _msg->from->body.len + 1, ft_body);
00692                         if (ft_body->error == PARSE_ERROR) {
00693                                 LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to parse From header\n");
00694                                 pkg_free(ft_body);
00695                                 if (_msg->REQ_METHOD != METHOD_ACK) {
00696                                         if (sl.reply(_msg, 400, "Bad From header") == -1) {
00697                                                 LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to send 400 via send_reply (bad from header)\n");
00698                                         }
00699                                 }
00700                                 return SANITY_CHECK_FAILED;
00701                         }
00702                         _msg->from->parsed = ft_body;
00703                         ft_body = NULL;
00704                 }
00705                 if (((struct to_body*)_msg->from->parsed)->uri.s) {
00706 #ifdef EXTRA_DEBUG
00707                         DBG("check_parse_uris(): parsing From URI\n");
00708 #endif
00709                         if (parse_uri(((struct to_body*)_msg->from->parsed)->uri.s, 
00710                                         ((struct to_body*)_msg->from->parsed)->uri.len, &uri) != 0) {
00711                             LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to parse From uri\n");
00712                             if (_msg->REQ_METHOD != METHOD_ACK) {
00713                                 if (sl.reply(_msg, 400, "Bad From URI") == -1) {
00714                                     LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to send 400 via send_reply (bad from uri)\n");
00715                                 }
00716                             }
00717                             return SANITY_CHECK_FAILED;
00718                         }
00719                         /* FIXME: we should store this parsed struct somewhere so that
00720                          * it could be re-used */
00721                         /* FIXME 2: would it make sense to check here for "mandatory"
00722                          * or "requested" parts of the URI? */
00723                 }
00724         }
00725         /* check To URI */
00726         if (SANITY_URI_CHECK_TO & checks) {
00727 #ifdef EXTRA_DEBUG
00728                 DBG("check_parse_uris(): looking up To header\n");
00729 #endif
00730                 if ((!_msg->to && parse_headers(_msg, HDR_TO_F, 0) != 0) || !_msg->to) {
00731                         LOG(L_WARN, "sanity_check(): check_parse_uris(): missing to header\n");
00732                         if (_msg->REQ_METHOD != METHOD_ACK) {
00733                                 if (sl.reply(_msg, 400, "Missing To Header") == -1) {
00734                                         LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to send 400 via send_reply (missing To)\n");
00735                                 }
00736                         }
00737                         return SANITY_CHECK_FAILED;
00738                 }
00739                 /* parse_to is automatically called for HDR_TO_F */
00740                 if (!_msg->to->parsed) {
00741                         LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to parse To header\n");
00742                         if (_msg->REQ_METHOD != METHOD_ACK) {
00743                                 if (sl.reply(_msg, 400, "Bad To URI") == -1) {
00744                                         LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to send 400 via send_reply (bad to uri)\n");
00745                                 }
00746                         }
00747                         return SANITY_CHECK_FAILED;
00748                 }
00749                 if (((struct to_body*)_msg->to->parsed)->uri.s) {
00750 #ifdef EXTRA_DEBUG
00751                         DBG("check_parse_uris(): parsing To URI\n");
00752 #endif
00753                         if (parse_uri(((struct to_body*)_msg->to->parsed)->uri.s, 
00754                                         ((struct to_body*)_msg->to->parsed)->uri.len, &uri) != 0) {
00755                                 LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to parse To uri\n");
00756                                 if (_msg->REQ_METHOD != METHOD_ACK) {
00757                                         if (sl.reply(_msg, 400, "Bad To URI") == -1) {
00758                                                 LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to send 400 via send_reply (bad to uri)\n");
00759                                         }
00760                                 }
00761                                 return SANITY_CHECK_FAILED;
00762                         }
00763                         /* FIXME: we should store this parsed struct somewhere so that
00764                          * it could be re-used */
00765                         /* FIXME 2: would it make sense to check here for "mandatory"
00766                          * or "requested" parts of the URI? */
00767                 }
00768         }
00769         /* check Contact URI */
00770         if (SANITY_URI_CHECK_CONTACT & checks) {
00771 #ifdef EXTRA_DEBUG
00772                 DBG("check_parse_uris(): looking up Contact header\n");
00773 #endif
00774                 if ((!_msg->contact && parse_headers(_msg, HDR_CONTACT_F, 0) != 0) || !_msg->contact) {
00775                         LOG(L_WARN, "sanity_check(): check_parse_uris(): missing contact header\n");
00776                 }
00777                 if (_msg->contact) {
00778 #ifdef EXTRA_DEBUG
00779                         DBG("check_parse_uris(): parsing Contact header\n");
00780 #endif
00781                         if (parse_contact(_msg->contact) < 0) {
00782                                 LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to parse Contact header\n");
00783                                 if (_msg->REQ_METHOD != METHOD_ACK) {
00784                                         if (sl.reply(_msg, 400, "Bad Contact Header") == -1) {
00785                                                 LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to send 400 via send_reply (bad Contact)\n");
00786                                         }
00787                                 }
00788                                 return SANITY_CHECK_FAILED;
00789                         }
00790                         if (parse_uri(((struct contact_body*)_msg->contact->parsed)->contacts->uri.s,
00791                                         ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len, &uri) != 0) {
00792                                 LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to parse Contact uri\n");
00793                                 if (_msg->REQ_METHOD != METHOD_ACK) {
00794                                         if (sl.reply(_msg, 400, "Bad Contact URI") == -1) {
00795                                                 LOG(L_WARN, "sanity_check(): check_parse_uris(): failed to send 400 via send_reply (bad Contact uri)\n");
00796                                         }
00797                                 }
00798                                 return SANITY_CHECK_FAILED;
00799                         }
00800                 }
00801         }
00802 
00803 #ifdef EXTRA_DEBUG
00804         DBG("check_parse_uris passed\n");
00805 #endif
00806         return SANITY_CHECK_PASSED;
00807 }
00808 
00809 
00810 /* Make sure that username attribute in all digest credentials
00811  * instances has a meaningful value
00812  */
00813 int check_digest(struct sip_msg* msg, int checks)
00814 {
00815     struct hdr_field* ptr;
00816     dig_cred_t* cred;
00817     int ret;
00818     int hf_type;
00819 
00820     if (parse_headers(msg, HDR_EOH_F, 0) != 0) {
00821         LOG(L_ERR, "sanity_check(): check_digest: failed to parse proxy require header\n");
00822         return SANITY_CHECK_FAILED;
00823     }
00824 
00825     if (!msg->authorization && !msg->proxy_auth) {
00826 #ifdef EXTRA_DEBUG
00827         DBG("sanity_check(): check_digest: Nothing to check\n");
00828 #endif
00829         return SANITY_CHECK_PASSED;
00830     }
00831 
00832     if (msg->authorization) {
00833         hf_type = HDR_AUTHORIZATION_T;
00834         ptr = msg->authorization;
00835     } else {
00836         hf_type = HDR_PROXYAUTH_T;
00837         ptr = msg->proxy_auth;
00838     }
00839     while(ptr) {
00840         if ((ret = parse_credentials(ptr)) != 0) {
00841             DBG("sanity_check(): check_digest: Cannot parse credentials: %d\n", ret);
00842             return SANITY_CHECK_FAILED;
00843         }
00844 
00845         cred = &((auth_body_t*)ptr->parsed)->digest;
00846 
00847         if (check_dig_cred(cred) != E_DIG_OK) {
00848 #ifdef EXTRA_DEBUG
00849             DBG("sanity_check(): check_digest: Digest credentials malformed\n");
00850 #endif
00851             return SANITY_CHECK_FAILED;
00852         }
00853 
00854         if (cred->username.whole.len == 0) {
00855 #ifdef EXTRA_DEBUG
00856             DBG("sanity_check(): check_digest: Empty username\n");
00857 #endif
00858             return SANITY_CHECK_FAILED;
00859         }
00860         
00861         if (cred->nonce.len == 0) {
00862 #ifdef EXTRA_DEBUG
00863             DBG("sanity_check(): check_digest: Empty nonce attribute\n");
00864 #endif
00865             return SANITY_CHECK_FAILED;
00866         }
00867 
00868         if (cred->response.len == 0) {
00869 #ifdef EXTRA_DEBUG
00870             DBG("sanity_check(): check_digest: Empty response attribute\n");
00871 #endif
00872             return SANITY_CHECK_FAILED;
00873         }
00874 
00875         do {
00876             ptr = ptr->next;
00877         } while(ptr && ptr->type != hf_type);
00878 
00879         if (!ptr && hf_type == HDR_AUTHORIZATION_T) {
00880             hf_type = HDR_PROXYAUTH_T;
00881             ptr = msg->proxy_auth;
00882         }
00883     }
00884 
00885     return SANITY_CHECK_PASSED;
00886 }

Generated on Tue Sep 7 04:16:07 2010 for SIPExpressRouter by  doxygen 1.3.9.1