auth_hdrs.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (c) 2007 iptelorg GmbH
00005  *
00006  * This file is part of SIP-router, a free SIP server.
00007  *
00008  * SIP-router is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * SIP-router is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00030 #include <errno.h>
00031 
00032 #include "../../parser/parser_f.h"
00033 #include "../../parser/parse_from.h"
00034 #include "../../parser/parse_cseq.h"
00035 #include "../../parser/parse_content.h"
00036 #include "../../parser/parse_uri.h"
00037 #include "../../parser/keys.h"
00038 #include "../../parser/contact/parse_contact.h"
00039 
00040 #include "../../modules/tm/ut.h"
00041 #include "../../data_lump.h"
00042 #include "../../msg_translator.h"
00043 #include "auth_identity.h"
00044 
00045 
00046 struct hdr_field glb_contact;
00047 char *glb_siphdr=NULL;
00048 char *glb_msgbody=NULL;
00049 
00050 static int tohdr_proc(str *sout, str *soutopt, struct sip_msg *msg);
00051 static int in_contacthdr_proc(str *sout, str *soutopt, struct sip_msg *msg);
00052 static int out_contacthdr_proc(str *sout, str *soutopt, struct sip_msg *msg);
00053 static int in_msgbody_proc(str *sout, str *soutopt, struct sip_msg *msg);
00054 static int out_msgbody_proc(str *sout, str *soutopt, struct sip_msg *msg);
00055 static void free_out_contacthdr(void);
00056 static void free_out_msgbody(void);
00057 
00058 
00059 /* macros from the core parser */
00060 #define LOWER_BYTE(b) ((b) | 0x20)
00061 #define LOWER_DWORD(d) ((d) | 0x20202020)
00062 
00063 #define READ(val) \
00064 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
00065 
00066 static char *auth_next_line(char *buf, char *buf_end);
00067 static inline char* skip_ws(char* p, unsigned int size);
00068 static char *auth_get_hf_name(char *begin, char *end, enum _hdr_types_t *type);
00069 static int get_contact_body(char *buf, unsigned int len, str *sout);
00070 
00071 
00072 /*
00073  *      Header parsing functions
00074  */
00075 
00076 /* From */
00077 int fromhdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
00078 {
00079         if ((!msg->from) && (parse_headers(msg, HDR_FROM_F, 0) == -1)) {
00080                 LOG(L_ERR, "AUTH_IDENTITY:fromhdr_proc: Error while parsing FROM header\n");
00081                 return AUTH_ERROR;
00082         }
00083         if (!msg->from) {
00084                 LOG(L_ERR, "AUTH_IDENTITY:fromhdr_proc: FROM header field is not found\n");
00085                 return AUTH_NOTFOUND;
00086         }
00087         /* we must call parse_from_header explicitly */
00088         if ((!(msg->from)->parsed) && (parse_from_header(msg) < 0)) {
00089                 LOG(L_ERR, "AUTH_IDENTITY:fromhdr_proc: Error while parsing FROM body\n");
00090                 return AUTH_ERROR;
00091         }
00092 
00093         if (sout)
00094                 *sout=get_from(msg)->uri;
00095 
00096         if (soutopt)
00097                 *soutopt=get_from(msg)->tag_value;
00098 
00099         return AUTH_OK;
00100 }
00101 
00102 /* To */
00103 static int tohdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
00104 {
00105         if (!msg->to && (parse_headers(msg, HDR_TO_F, 0) == -1)) {
00106                 LOG(L_ERR, "AUTH_IDENTITY:tohdr_proc: Error while parsing TO header\n");
00107                 return AUTH_ERROR;
00108         }
00109         if (!msg->to) {
00110                 LOG(L_ERR, "AUTH_IDENTITY:tohdr_proc: TO header field is not found\n");
00111                 return AUTH_NOTFOUND;
00112         }
00113         if (!msg->to->parsed) {
00114                 LOG(L_ERR, "AUTH_IDENTITY:tohdr_proc: TO is not parsed\n");
00115                 return AUTH_ERROR;
00116         }
00117 
00118         if (sout)
00119                 *sout=((struct to_body*)msg->to->parsed)->uri;
00120 
00121         return AUTH_OK;
00122 }
00123 
00124 /* Call-ID */
00125 int callidhdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
00126 {
00127         if (!msg->callid && (parse_headers(msg, HDR_CALLID_F, 0) == -1)) {
00128                 LOG(L_ERR, "AUTH_IDENTITY:callidhdr_proc: error while parsing CALLID header\n");
00129                 return AUTH_ERROR;
00130         }
00131         if (!msg->callid) {
00132                 LOG(L_ERR, "AUTH_IDENTITY:callidhdr_proc: CALLID header field is not found\n");
00133                 return AUTH_NOTFOUND;
00134         }
00135 
00136         if (sout)
00137                 *sout=msg->callid->body;
00138 
00139         return AUTH_OK;
00140 }
00141 
00142 /* CSeq */
00143 int cseqhdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
00144 {
00145         if (!msg->cseq && (parse_headers(msg, HDR_CSEQ_F, 0) == -1)) {
00146                 LOG(L_ERR, "AUTH_IDENTITY:cseqhdr_proc: Error while parsing CSEQ header\n");
00147                 return AUTH_ERROR;
00148         }
00149         if (!msg->cseq) {
00150                 LOG(L_ERR, "AUTH_IDENTITY:cseqhdr_proc: CSEQ header field is not found\n");
00151                 return AUTH_NOTFOUND;
00152         }
00153         if (!msg->cseq->parsed) {
00154                 LOG(L_ERR, "AUTH_IDENTITY:cseqhdr_proc: CSEQ is not parsed\n");
00155                 return AUTH_ERROR;
00156         }
00157 
00158         if (sout)
00159                 *sout=get_cseq(msg)->number;
00160         if (soutopt)
00161                 *soutopt=get_cseq(msg)->method;
00162 
00163         return AUTH_OK;
00164 }
00165 
00166 /* Date */
00167 int datehdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
00168 {
00169         if ((!msg->date) && (parse_headers(msg, HDR_DATE_F, 0) == -1)) {
00170                 LOG(L_ERR, "AUTH_IDENTITY:datehdr_proc: Error while parsing DATE header\n");
00171                 return AUTH_ERROR;
00172         }
00173         if (!msg->date) {
00174                 LOG(AUTH_DBG_LEVEL, "AUTH_IDENTITY:datehdr_proc: DATE header field is not found\n");
00175                 return AUTH_NOTFOUND;
00176         }
00177         /* we must call parse_date_header explicitly */
00178         if ((!(msg->date)->parsed) && (parse_date_header(msg) < 0)) {
00179                 LOG(L_ERR, "AUTH_IDENTITY:datehdr_proc: Error while parsing DATE body\n");
00180                 return AUTH_ERROR;
00181         }
00182 
00183         if (sout)
00184                 *sout=msg->date->body;
00185 
00186         return AUTH_OK;
00187 }
00188 
00189 /* Contact header of the incoming SIP message */
00190 static int in_contacthdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
00191 {
00192         if (!msg->contact && (parse_headers(msg, HDR_CONTACT_F, 0) == -1)) {
00193                 LOG(L_ERR, "AUTH_IDENTITY:in_contacthdr_proc: Error while parsing CONTACT header\n");
00194                 return AUTH_ERROR;
00195         }
00196         if (!msg->contact) {
00197                 return AUTH_NOTFOUND;
00198         }
00199         /* we must call parse_contact explicitly */
00200         if (!msg->contact->parsed && (parse_contact(msg->contact) < 0)) {
00201                 LOG(L_ERR, "AUTH_IDENTITY:in_contacthdr_proc: Error while parsing CONTACT body\n");
00202                 return AUTH_ERROR;
00203         }
00204 
00205         if (sout)
00206                 *sout=((contact_body_t*)msg->contact->parsed)->contacts->uri;
00207 
00208         return AUTH_OK;
00209 }
00210 
00211 /* Contact header of the outgoing SIP message */
00212 static int out_contacthdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
00213 {
00214         unsigned int ulen;
00215         int ierror;
00216         struct dest_info dst;
00217         int ires;
00218 
00219 
00220 #ifdef USE_DNS_FAILOVER
00221         /* get info about outbound socket */
00222         if ((uri2dst(NULL, &dst, msg, GET_NEXT_HOP(msg), PROTO_NONE) == 0)
00223 #else
00224         if ((uri2dst(&dst, msg, GET_NEXT_HOP(msg), PROTO_NONE) == 0)
00225 #endif
00226                 || (dst.send_sock == 0)) {
00227                 LOG(L_ERR, "AUTH_IDENTITY:out_contacthdr_proc: Can't determinate destination socket\n");
00228                 return -1;
00229         }
00230 
00231         /* we save it to global variable because we'll process it later */
00232         glb_siphdr=build_only_headers(msg, 1, &ulen, &ierror, &dst);
00233 
00234         if (ierror)
00235                 return -2;
00236 
00237         memset(&glb_contact, 0, sizeof(glb_contact));
00238 
00239         /* parse_contact() needs only the body element of "struct hdr_field" */
00240         ires=get_contact_body(glb_siphdr, ulen, &glb_contact.body);
00241         if (ires==AUTH_NOTFOUND) {
00242                 pkg_free(glb_siphdr); glb_siphdr=NULL;
00243                 return AUTH_NOTFOUND;
00244         }
00245         if (ires!=AUTH_OK) {
00246                 pkg_free(glb_siphdr); glb_siphdr=NULL;
00247                 return AUTH_ERROR;
00248         }
00249 
00250         if (parse_contact(&glb_contact) < 0) {
00251                 pkg_free(glb_siphdr); glb_siphdr=NULL;
00252                 return AUTH_ERROR;
00253         }
00254 
00255         if (sout)
00256                 *sout=((contact_body_t*)glb_contact.parsed)->contacts->uri;
00257 
00258         return AUTH_OK;
00259 }
00260 
00261 /* Identity */
00262 int identityhdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
00263 {
00264         if (!msg->identity && (parse_headers(msg, HDR_IDENTITY_F, 0) == -1)) {
00265                 LOG(L_ERR, "AUTH_IDENTITY:identityhdr_proc: Error while parsing IDENTITY header\n");
00266                 return AUTH_ERROR;
00267         }
00268         if (!msg->identity) {
00269                 return AUTH_NOTFOUND;
00270         }
00271         /* we must call parse_identityinfo_header explicitly */
00272         if ((!(msg->identity)->parsed) && (parse_identity_header(msg) < 0)) {
00273                 LOG(L_ERR, "AUTH_IDENTITY:identityhdr_proc: Error while parsing IDENTITY body\n");
00274                 return AUTH_ERROR;
00275         }
00276 
00277         if (sout)
00278                 *sout=get_identity(msg)->hash;
00279 
00280         return AUTH_OK;
00281 }
00282 
00283 /* Identity-info */
00284 int identityinfohdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
00285 {
00286         if (!msg->identity_info && (parse_headers(msg, HDR_IDENTITY_INFO_F, 0) == -1)) {
00287                 LOG(L_ERR, "AUTH_IDENTITY:identityinfohdr_proc: Error while parsing IDENTITY-INFO header\n");
00288                 return AUTH_ERROR;
00289         }
00290         if (!msg->identity_info) {
00291                 LOG(L_ERR, "AUTH_IDENTITY:identityinfohdr_proc: IDENTITY-INFO header field is not found\n");
00292                 return AUTH_NOTFOUND;
00293         }
00294         /* we must call parse_identityinfo_header explicitly */
00295         if ((!(msg->identity_info)->parsed) && (parse_identityinfo_header(msg) < 0)) {
00296                 LOG(L_ERR, "AUTH_IDENTITY:identityinfohdr_proc: Error while parsing IDENTITY-INFO body\n");
00297                 return AUTH_ERROR;
00298         }
00299 
00300         if (sout)
00301                 *sout=get_identityinfo(msg)->uri;
00302         if (soutopt)
00303                 *soutopt=get_identityinfo(msg)->domain;
00304 
00305         return AUTH_OK;
00306 }
00307 
00308 /* body of the incoming SIP message */
00309 static int in_msgbody_proc(str *sout, str *soutopt, struct sip_msg *msg)
00310 {
00311         if (!sout)
00312                 return AUTH_OK;
00313 
00314         sout->s = get_body(msg);
00315         if (!sout->s || sout->s[0] == 0) {
00316                 sout->len = 0;
00317         } else {
00318                 if (!msg->content_length) {
00319                         LOG(L_ERR, "AUTH_IDENTITY:route_msgbody_proc: no Content-Length header found!\n");
00320                         return AUTH_ERROR;
00321                 }
00322                 sout->len = get_content_length(msg);
00323         }
00324 
00325         return AUTH_OK;
00326 }
00327 
00328 /* body of the outgoing SIP message */
00329 static int out_msgbody_proc(str *sout, str *soutopt, struct sip_msg *msg)
00330 {
00331 
00332         unsigned int len;
00333         int    err;
00334         struct dest_info dst;
00335         char scontentlen[AUTH_CONTENTLENGTH_LENGTH];
00336 
00337 
00338         if (!sout)
00339                 return AUTH_OK;
00340 
00341 #ifdef USE_DNS_FAILOVER
00342         /* get info about outbound socket */
00343         if ((uri2dst(NULL, &dst, msg, GET_NEXT_HOP(msg), PROTO_NONE) == 0)
00344 #else
00345         if ((uri2dst(&dst, msg, GET_NEXT_HOP(msg), PROTO_NONE) == 0)
00346 #endif
00347                 || (dst.send_sock == 0)) {
00348                 LOG(L_ERR, "AUTH_IDENTITY:rtend_msgbody_proc: Can't determinate destination socket\n");
00349                 return -1;
00350         }
00351 
00352         /* we save it to global variable too to be able to free it later */
00353         sout->s = glb_msgbody = build_body(msg, &len, &err, &dst);
00354         if (err) {
00355                 LOG(L_ERR, "AUTH_IDENTITY:rtend_msgbody_proc: Can't build body (%d)\n", err);
00356                 return -2;
00357         }
00358 
00359         sout->len = (int)len;
00360 
00361         /* authentication services MUST add a Content-Length header field to
00362          * SIP requests if one is not already present
00363          *
00364          * content-length (if present) must be already parsed and if destination
00365          * protocol is not UDP then core will append Content-Length
00366          */
00367         if (!msg->content_length && dst.proto==PROTO_UDP) {
00368                 snprintf(scontentlen, sizeof(scontentlen), "Content-Length: %d\r\n", len);
00369                 scontentlen[sizeof(scontentlen)-1]=0;
00370                 /* if HDR_CONTENTLENGTH_T's specified then the header won't be added! */
00371                 if (append_hf(msg, scontentlen, HDR_OTHER_T)) {
00372                         pkg_free(glb_msgbody);
00373                         glb_msgbody=NULL;
00374                         return -3;
00375                 }
00376         }
00377 
00378         return AUTH_OK;
00379 }
00380 
00381 /* Contact header deinitializer of outgoing message */
00382 static void free_out_contacthdr(void)
00383 {
00384         void** h_parsed;
00385 
00386         h_parsed=&glb_contact.parsed; /*strict aliasing warnings workarround */
00387         if (glb_siphdr) {
00388                 pkg_free(glb_siphdr);
00389                 glb_siphdr=NULL;
00390         }
00391 
00392         if (glb_contact.parsed)
00393                 free_contact((contact_body_t**)h_parsed);
00394 }
00395 
00396 /* body deinitializer of the outgoing message */
00397 static void free_out_msgbody(void)
00398 {
00399         if (glb_msgbody) {
00400                 pkg_free(glb_msgbody);
00401                 glb_msgbody=NULL;
00402         }
00403 }
00404 
00405 /* Digest-string assebmler function (RFC 4474 [9] */
00406 int digeststr_asm(dynstr *sout, struct sip_msg *msg, str *sdate, int iflags)
00407 {
00408         /* incoming SIP message parser describer */
00409         dgst_part incoming_sip_digest_desc[] = {
00410                 { DS_FROM, fromhdr_proc, NULL, DS_REQUIRED },
00411                 { DS_TO, tohdr_proc, NULL, DS_REQUIRED },
00412                 { DS_CALLID, callidhdr_proc, NULL, DS_REQUIRED },
00413                 { DS_CSEQ, cseqhdr_proc, NULL, DS_REQUIRED },
00414                 { DS_DATE, datehdr_proc, NULL, DS_NOTREQUIRED },
00415                 { DS_CONTACT, in_contacthdr_proc, NULL, DS_NOTREQUIRED },
00416                 { DS_BODY, in_msgbody_proc, NULL, DS_NOTREQUIRED },
00417                 { 0, NULL, NULL, 0 }
00418         };
00419         /* outgoing SIP message parser describer */
00420         dgst_part outgoing_sip_digest_desc[] = {
00421                 { DS_FROM, fromhdr_proc, NULL, DS_REQUIRED },
00422                 { DS_TO, tohdr_proc, NULL, DS_REQUIRED },
00423                 { DS_CALLID, callidhdr_proc, NULL, DS_REQUIRED },
00424                 { DS_CSEQ, cseqhdr_proc, NULL, DS_REQUIRED },
00425                 { DS_DATE, datehdr_proc, NULL, DS_NOTREQUIRED },
00426                 { DS_CONTACT, out_contacthdr_proc, free_out_contacthdr, DS_NOTREQUIRED },
00427                 { DS_BODY, out_msgbody_proc, free_out_msgbody, DS_NOTREQUIRED },
00428                 { 0, NULL, NULL, 0 }
00429         };
00430         dgst_part *pactpart;
00431         dgst_part *sip_digest_desc;
00432         str sact, sactopt;
00433         int i1;
00434         int iRes;
00435 
00436 
00437         if ((iflags & AUTH_INCOMING_BODY) ^ (iflags & AUTH_OUTGOING_BODY)) {
00438                 (iflags & AUTH_INCOMING_BODY) ?
00439                         (sip_digest_desc = incoming_sip_digest_desc) :
00440                         (sip_digest_desc = outgoing_sip_digest_desc);
00441         } else
00442                 /* AUTH_INCOMING_BODY or AUTH_OUTGOING_BODY flag must set */
00443                 return -1;
00444 
00445         resetstr_dynstr(sout);
00446 
00447         for (pactpart=&sip_digest_desc[0],i1=0; pactpart[i1].itype; i1++) {
00448                 iRes=pactpart[i1].pfunc(&sact, &sactopt, msg);
00449 
00450                 /* there was an error or the required header is missing */
00451                 if (iRes==AUTH_ERROR
00452                     || (iRes==AUTH_NOTFOUND && (pactpart[i1].iflag & DS_REQUIRED)))
00453                         return -1;
00454 
00455                 switch (pactpart[i1].itype) {
00456                         /* Cseq handle (we need SP instead of LWS (RFC4474 [9])) */
00457                         case DS_CSEQ:
00458                                 if (app2dynstr(sout,&sact))
00459                                         return -1;
00460                                 if (app2dynchr(sout,' '))
00461                                         return -2;
00462                                 if (app2dynstr(sout,&sactopt))
00463                                         return -3;
00464                                 break;
00465                         case DS_DATE:
00466                                 if (iRes==AUTH_NOTFOUND) {
00467                                         if (iflags & AUTH_ADD_DATE) {
00468                                                 if (app2dynstr(sout,sdate))
00469                                                         return -8;
00470                                         } else {
00471                                                 /* Date header must exist */
00472                                                 LOG(L_ERR, "AUTH_IDENTITY:digeststr_asm: DATE header is not found\n");
00473                                                 return -9;
00474                                         }
00475                                 }
00476                         default:
00477                                 if (iRes==AUTH_NOTFOUND)
00478                                         break;
00479                                 if (app2dynstr(sout,&sact))
00480                                         return -10;
00481                 }
00482 
00483                 /* if there is desctructor function available then we call it */
00484                 if (pactpart[i1].pfreefunc)
00485                         pactpart[i1].pfreefunc();
00486 
00487                 /* we don't add separator after message body */
00488                 if (pactpart[i1+1].itype) {
00489                         /* we append the separator */
00490                         if (app2dynchr(sout,'|'))
00491                                 return -11;
00492                 }
00493         }
00494 
00495         return 0;
00496 }
00497 
00498 /* copypasted and ripped from ser/modules/textops/textops.c) */
00499 int append_hf(struct sip_msg* msg, char *str1, enum _hdr_types_t type)
00500 {
00501         struct lump* anchor;
00502         char* s;
00503         int len;
00504 
00505         if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
00506                 LOG(L_ERR, "AUTH_IDENTITY:append_hf: Error while parsing message\n");
00507                 return -1;
00508         }
00509 
00510         anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, type);
00511         if (anchor == 0) {
00512                 LOG(L_ERR, "AUTH_IDENTITY:append_hf: Can't get anchor\n");
00513                 return -1;
00514         }
00515 
00516         len=strlen(str1);
00517 
00518         s = (char*)pkg_malloc(len);
00519         if (!s) {
00520                 LOG(L_ERR, "AUTH_IDENTITY:append_hf: No memory left\n");
00521                 return -1;
00522         }
00523 
00524         memcpy(s, str1, len);
00525 
00526         if (insert_new_lump_before(anchor, s, len, type) == 0) {
00527                 LOG(L_ERR, "AUTH_IDENTITY:append_hf: Can't insert lump\n");
00528                 pkg_free(s);
00529                 return -1;
00530         }
00531         return 0;
00532 }
00533 
00534 /* get the current system date and appends it to the message */
00535 int append_date(str *sdate, int idatesize, time_t *tout, struct sip_msg *msg)
00536 {
00537         char date_hf[AUTH_TIME_LENGTH];
00538         char date_str[AUTH_TIME_LENGTH];
00539         time_t tdate_now;
00540         struct tm *bd_time;
00541         size_t ilen;
00542         int istrlen;
00543 
00544 
00545         if ((tdate_now=time(0)) < 0) {
00546                 LOG(L_ERR, "AUTH_IDENTITY:append_date: time error %s\n", strerror(errno));
00547                 return -1;
00548         }
00549         if (!(bd_time=gmtime(&tdate_now))) {
00550                 LOG(L_ERR, "AUTH_IDENTITY:append_date: gmtime error\n");
00551                 return -2;
00552         }
00553 
00554         ilen=strftime(date_str, sizeof(date_str), AUTH_TIME_FORMAT, bd_time);
00555         if (ilen > sizeof(date_hf) - strlen("Date: \r\n") || ilen==0) {
00556                 LOG(L_ERR, "AUTH_IDENTITY:append_date: unexpected time length\n");
00557                 return -3;
00558         }
00559 
00560         /* we append the date header to the message too */
00561         istrlen=strlen("Date: ");
00562         memcpy(date_hf,"Date: ",istrlen);
00563         memcpy(date_hf+istrlen,date_str,ilen);
00564         istrlen+=ilen;
00565         date_hf[istrlen]='\r'; date_hf[istrlen+1]='\n'; date_hf[istrlen+2]=0;
00566         if (append_hf(msg, date_hf, HDR_DATE_T))
00567                 return -4;
00568 
00569         if (sdate && idatesize >= ilen) {
00570                 memcpy(sdate->s, date_str, ilen);
00571                 sdate->len=ilen;
00572         } else
00573                 return -5;
00574                 if (tout)
00575                         *tout=tdate_now;
00576 
00577         return 0;
00578 }
00579 
00580 /*
00581  *
00582  *      "Contact" header parser part
00583  *
00584  */
00585 
00586 
00587 /* returns a pointer to the next line */
00588 static char *auth_next_line(char *buf, char *buf_end)
00589 {
00590         char    *c;
00591 
00592         c = buf;
00593         do {
00594                 while ((c < buf_end) && (*c != '\n')) c++;
00595                 if (c < buf_end) c++;
00596                 if ((c < buf_end) && (*c == '\r')) c++;
00597 
00598         } while ((c < buf_end) && ((*c == ' ') || (*c == '\t')));       /* next line begins with whitespace line folding */
00599 
00600         return c;
00601 }
00602 
00603 /*
00604  * Skip all white-chars and return position of the first
00605  * non-white char
00606  */
00607 static inline char* skip_ws(char* p, unsigned int size)
00608 {
00609         char* end;
00610 
00611         end = p + size;
00612         for(; p < end; p++) {
00613                 if ((*p != ' ') && (*p != '\t')) return p;
00614         }
00615         return p;
00616 }
00617 
00618 /* looks for "Contact" header */
00619 static char *auth_get_hf_name(char *begin, char *end, enum _hdr_types_t *type)
00620 {
00621         char *p;
00622         unsigned int val;
00623 
00624 
00625         if (end - begin < 4) {
00626                 *type = HDR_ERROR_T;
00627                 return begin;
00628         }
00629 
00630         p = begin;
00631         val = LOWER_DWORD(READ(p));
00632 
00633         switch(val) {
00634                 case _cont_:    /* Content-Length */
00635                         p+=4;
00636                         switch (LOWER_DWORD(READ(p))) {
00637                         case _act1_:
00638                                 *type = HDR_CONTACT_T;
00639                                 return (p + 4);
00640                         case _act2_:
00641                                 *type = HDR_CONTACT_T;
00642                                 p += 4;
00643                                 goto dc_end;
00644                         }
00645                 default:
00646                         /* compact headers */
00647                         switch(LOWER_BYTE(*p)) {
00648                         case 'm':
00649                                 switch(*(p + 1)) {
00650                                 case ' ':
00651                                         *type = HDR_CONTACT_T;
00652                                         p += 2;
00653                                         goto dc_end;
00654                                 case ':':
00655                                         *type = HDR_CONTACT_T;
00656                                         return (p + 2);
00657                                 }
00658                         default:
00659                                 *type = HDR_OTHER_T;
00660                                 break;
00661                         }
00662         }
00663 
00664 dc_end:
00665         p = skip_ws(p, end - p);
00666         if (*p != ':') {
00667                 goto other;
00668         } else {
00669                 return (p + 1);
00670         }
00671 
00672         /* Unknown header type */
00673 other:
00674         p = q_memchr(p, ':', end - p);
00675         if (!p) {        /* No double colon found, error.. */
00676                 *type = HDR_ERROR_T;
00677                 return 0;
00678         } else {
00679                 *type = HDR_OTHER_T;
00680                 return (p + 1);
00681         }
00682 
00683         return p;
00684 }
00685 
00686 /* parses buffer that contains a SIP message header, looks for "Contact"
00687    header field and returns the value of that */
00688 static int get_contact_body(char *buf, unsigned int len, str *sout)
00689 {
00690         char *end, *s, *tmp, *match;
00691         enum _hdr_types_t hf_type;
00692 
00693 
00694         end = buf + len;
00695         s = buf;
00696 
00697         memset(sout, 0, sizeof(*sout));
00698 
00699         while (s < end) {
00700                 if ((*s == '\n') || (*s == '\r')) {
00701                         /* end of SIP msg */
00702                         hf_type = HDR_EOH_T;
00703                 } else {
00704                         /* parse HF name */
00705                         if (!(s = auth_get_hf_name(s, end, &hf_type)))
00706                                 return AUTH_ERROR;
00707                 }
00708 
00709                 switch(hf_type) {
00710                         case HDR_CONTACT_T:
00711                                 tmp=eat_lws_end(s, end);
00712                                 if (tmp>=end) {
00713                                         LOG(L_ERR, "AUTH_IDENTITY:get_contact_body: get_hdr_field: HF empty\n");
00714                                         return AUTH_ERROR;
00715                                 }
00716                                 sout->s=tmp;
00717                                 /* find lf */
00718                                 do{
00719                                         match=q_memchr(tmp, '\n', end-tmp);
00720                                         if (match){
00721                                                 match++;
00722                                         }else {
00723                                                 LOG(L_ERR, "AUTH_IDENTITY:get_contact_body: bad msg body\n");
00724                                                 return AUTH_ERROR;
00725                                         }
00726                                         tmp=match;
00727                                 } while( match<end &&( (*match==' ')||(*match=='\t') ) );
00728                                 tmp=match;
00729                                 sout->len=match-sout->s;
00730                                 trim_r(*sout);
00731                                 return AUTH_OK;
00732                                 break;
00733                         case HDR_ERROR_T:
00734                                 return AUTH_ERROR;
00735                         default:
00736                                 s = auth_next_line(s, end);
00737                 }
00738         }
00739 
00740         return AUTH_NOTFOUND;
00741 }