1 /*
2 * This file is part of Kamailio, a free SIP server.
3 *
4 * Kamailio is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version
8 *
9 * Kamailio is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 * Copyright (c) 2007 iptelorg GmbH
19 *
20 */
21
22 /*!
23 * \file
24 * \brief Kamailio auth-identity :: Authentication headers
25 * \ingroup auth-identity
26 * Module: \ref auth-identity
27 */
28
29 #include <errno.h>
30
31 #include "../../core/parser/parser_f.h"
32 #include "../../core/parser/parse_from.h"
33 #include "../../core/parser/parse_cseq.h"
34 #include "../../core/parser/parse_content.h"
35 #include "../../core/parser/parse_uri.h"
36 #include "../../core/parser/keys.h"
37 #include "../../core/parser/contact/parse_contact.h"
38
39 #include "../../modules/tm/ut.h"
40 #include "../../core/data_lump.h"
41 #include "../../core/msg_translator.h"
42 #include "auth_identity.h"
43
44
45 struct hdr_field glb_contact;
46 char *glb_siphdr=NULL;
47 char *glb_msgbody=NULL;
48
49 static int tohdr_proc(str *sout, str *soutopt, struct sip_msg *msg);
50 static int in_contacthdr_proc(str *sout, str *soutopt, struct sip_msg *msg);
51 static int out_contacthdr_proc(str *sout, str *soutopt, struct sip_msg *msg);
52 static int in_msgbody_proc(str *sout, str *soutopt, struct sip_msg *msg);
53 static int out_msgbody_proc(str *sout, str *soutopt, struct sip_msg *msg);
54 static void free_out_contacthdr(void);
55 static void free_out_msgbody(void);
56
57
58 /* macros from the core parser */
59 #define LOWER_BYTE(b) ((b) | 0x20)
60 #define LOWER_DWORD(d) ((d) | 0x20202020)
61
62 #define READ(val) \
63 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
64
65 static char *auth_next_line(char *buf, char *buf_end);
66 static inline char* skip_ws(char* p, unsigned int size);
67 static char *auth_get_hf_name(char *begin, char *end, enum _hdr_types_t *type);
68 static int get_contact_body(char *buf, unsigned int len, str *sout);
69
70
71 /*
72 * Header parsing functions
73 */
74
75 /* From */
fromhdr_proc(str * sout,str * soutopt,struct sip_msg * msg)76 int fromhdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
77 {
78 if ((!msg->from) && (parse_headers(msg, HDR_FROM_F, 0) == -1)) {
79 LOG(L_ERR, "AUTH_IDENTITY:fromhdr_proc: Error while parsing FROM header\n");
80 return AUTH_ERROR;
81 }
82 if (!msg->from) {
83 LOG(L_ERR, "AUTH_IDENTITY:fromhdr_proc: FROM header field is not found\n");
84 return AUTH_NOTFOUND;
85 }
86 /* we must call parse_from_header explicitly */
87 if ((!(msg->from)->parsed) && (parse_from_header(msg) < 0)) {
88 LOG(L_ERR, "AUTH_IDENTITY:fromhdr_proc: Error while parsing FROM body\n");
89 return AUTH_ERROR;
90 }
91
92 if (sout)
93 *sout=get_from(msg)->uri;
94
95 if (soutopt)
96 *soutopt=get_from(msg)->tag_value;
97
98 return AUTH_OK;
99 }
100
101 /* To */
tohdr_proc(str * sout,str * soutopt,struct sip_msg * msg)102 static int tohdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
103 {
104 if (!msg->to && (parse_headers(msg, HDR_TO_F, 0) == -1)) {
105 LOG(L_ERR, "AUTH_IDENTITY:tohdr_proc: Error while parsing TO header\n");
106 return AUTH_ERROR;
107 }
108 if (!msg->to) {
109 LOG(L_ERR, "AUTH_IDENTITY:tohdr_proc: TO header field is not found\n");
110 return AUTH_NOTFOUND;
111 }
112 if (!msg->to->parsed) {
113 LOG(L_ERR, "AUTH_IDENTITY:tohdr_proc: TO is not parsed\n");
114 return AUTH_ERROR;
115 }
116
117 if (sout)
118 *sout=((struct to_body*)msg->to->parsed)->uri;
119
120 return AUTH_OK;
121 }
122
123 /* Call-ID */
callidhdr_proc(str * sout,str * soutopt,struct sip_msg * msg)124 int callidhdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
125 {
126 if (!msg->callid && (parse_headers(msg, HDR_CALLID_F, 0) == -1)) {
127 LOG(L_ERR, "AUTH_IDENTITY:callidhdr_proc: error while parsing CALLID header\n");
128 return AUTH_ERROR;
129 }
130 if (!msg->callid) {
131 LOG(L_ERR, "AUTH_IDENTITY:callidhdr_proc: CALLID header field is not found\n");
132 return AUTH_NOTFOUND;
133 }
134
135 if (sout)
136 *sout=msg->callid->body;
137
138 return AUTH_OK;
139 }
140
141 /* CSeq */
cseqhdr_proc(str * sout,str * soutopt,struct sip_msg * msg)142 int cseqhdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
143 {
144 if (!msg->cseq && (parse_headers(msg, HDR_CSEQ_F, 0) == -1)) {
145 LOG(L_ERR, "AUTH_IDENTITY:cseqhdr_proc: Error while parsing CSEQ header\n");
146 return AUTH_ERROR;
147 }
148 if (!msg->cseq) {
149 LOG(L_ERR, "AUTH_IDENTITY:cseqhdr_proc: CSEQ header field is not found\n");
150 return AUTH_NOTFOUND;
151 }
152 if (!msg->cseq->parsed) {
153 LOG(L_ERR, "AUTH_IDENTITY:cseqhdr_proc: CSEQ is not parsed\n");
154 return AUTH_ERROR;
155 }
156
157 if (sout)
158 *sout=get_cseq(msg)->number;
159 if (soutopt)
160 *soutopt=get_cseq(msg)->method;
161
162 return AUTH_OK;
163 }
164
165 /* Date */
datehdr_proc(str * sout,str * soutopt,struct sip_msg * msg)166 int datehdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
167 {
168 if ((!msg->date) && (parse_headers(msg, HDR_DATE_F, 0) == -1)) {
169 LOG(L_ERR, "AUTH_IDENTITY:datehdr_proc: Error while parsing DATE header\n");
170 return AUTH_ERROR;
171 }
172 if (!msg->date) {
173 LOG(AUTH_DBG_LEVEL, "AUTH_IDENTITY:datehdr_proc: DATE header field is not found\n");
174 return AUTH_NOTFOUND;
175 }
176 /* we must call parse_date_header explicitly */
177 if ((!(msg->date)->parsed) && (parse_date_header(msg) < 0)) {
178 LOG(L_ERR, "AUTH_IDENTITY:datehdr_proc: Error while parsing DATE body\n");
179 return AUTH_ERROR;
180 }
181
182 if (sout)
183 *sout=msg->date->body;
184
185 return AUTH_OK;
186 }
187
188 /* Contact header of the incoming SIP message */
in_contacthdr_proc(str * sout,str * soutopt,struct sip_msg * msg)189 static int in_contacthdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
190 {
191 if (!msg->contact && (parse_headers(msg, HDR_CONTACT_F, 0) == -1)) {
192 LOG(L_ERR, "AUTH_IDENTITY:in_contacthdr_proc: Error while parsing CONTACT header\n");
193 return AUTH_ERROR;
194 }
195 if (!msg->contact) {
196 return AUTH_NOTFOUND;
197 }
198 /* we must call parse_contact explicitly */
199 if (!msg->contact->parsed && (parse_contact(msg->contact) < 0)) {
200 LOG(L_ERR, "AUTH_IDENTITY:in_contacthdr_proc: Error while parsing CONTACT body\n");
201 return AUTH_ERROR;
202 }
203
204 if (sout)
205 *sout=((contact_body_t*)msg->contact->parsed)->contacts->uri;
206
207 return AUTH_OK;
208 }
209
210 /* Contact header of the outgoing SIP message */
out_contacthdr_proc(str * sout,str * soutopt,struct sip_msg * msg)211 static int out_contacthdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
212 {
213 unsigned int ulen;
214 int ierror;
215 struct dest_info dst;
216 int ires;
217
218
219 #ifdef USE_DNS_FAILOVER
220 /* get info about outbound socket */
221 if ((uri2dst(NULL, &dst, msg, GET_NEXT_HOP(msg), PROTO_NONE) == 0)
222 #else
223 if ((uri2dst(&dst, msg, GET_NEXT_HOP(msg), PROTO_NONE) == 0)
224 #endif
225 || (dst.send_sock == 0)) {
226 LOG(L_ERR, "AUTH_IDENTITY:out_contacthdr_proc: Can't determinate destination socket\n");
227 return -1;
228 }
229
230 /* we save it to global variable because we'll process it later */
231 glb_siphdr=build_only_headers(msg, 1, &ulen, &ierror, &dst);
232
233 if (ierror)
234 return -2;
235
236 memset(&glb_contact, 0, sizeof(glb_contact));
237
238 /* parse_contact() needs only the body element of "struct hdr_field" */
239 ires=get_contact_body(glb_siphdr, ulen, &glb_contact.body);
240 if (ires==AUTH_NOTFOUND) {
241 pkg_free(glb_siphdr); glb_siphdr=NULL;
242 return AUTH_NOTFOUND;
243 }
244 if (ires!=AUTH_OK) {
245 pkg_free(glb_siphdr); glb_siphdr=NULL;
246 return AUTH_ERROR;
247 }
248
249 if (parse_contact(&glb_contact) < 0) {
250 pkg_free(glb_siphdr); glb_siphdr=NULL;
251 return AUTH_ERROR;
252 }
253
254 if (sout)
255 *sout=((contact_body_t*)glb_contact.parsed)->contacts->uri;
256
257 return AUTH_OK;
258 }
259
260 /* Identity */
identityhdr_proc(str * sout,str * soutopt,struct sip_msg * msg)261 int identityhdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
262 {
263 if (!msg->identity && (parse_headers(msg, HDR_IDENTITY_F, 0) == -1)) {
264 LOG(L_ERR, "AUTH_IDENTITY:identityhdr_proc: Error while parsing IDENTITY header\n");
265 return AUTH_ERROR;
266 }
267 if (!msg->identity) {
268 return AUTH_NOTFOUND;
269 }
270 /* we must call parse_identityinfo_header explicitly */
271 if ((!(msg->identity)->parsed) && (parse_identity_header(msg) < 0)) {
272 LOG(L_ERR, "AUTH_IDENTITY:identityhdr_proc: Error while parsing IDENTITY body\n");
273 return AUTH_ERROR;
274 }
275
276 if (sout)
277 *sout=get_identity(msg)->hash;
278
279 return AUTH_OK;
280 }
281
282 /* Identity-info */
identityinfohdr_proc(str * sout,str * soutopt,struct sip_msg * msg)283 int identityinfohdr_proc(str *sout, str *soutopt, struct sip_msg *msg)
284 {
285 if (!msg->identity_info && (parse_headers(msg, HDR_IDENTITY_INFO_F, 0) == -1)) {
286 LOG(L_ERR, "AUTH_IDENTITY:identityinfohdr_proc: Error while parsing IDENTITY-INFO header\n");
287 return AUTH_ERROR;
288 }
289 if (!msg->identity_info) {
290 LOG(L_ERR, "AUTH_IDENTITY:identityinfohdr_proc: IDENTITY-INFO header field is not found\n");
291 return AUTH_NOTFOUND;
292 }
293 /* we must call parse_identityinfo_header explicitly */
294 if ((!(msg->identity_info)->parsed) && (parse_identityinfo_header(msg) < 0)) {
295 LOG(L_ERR, "AUTH_IDENTITY:identityinfohdr_proc: Error while parsing IDENTITY-INFO body\n");
296 return AUTH_ERROR;
297 }
298
299 if (sout)
300 *sout=get_identityinfo(msg)->uri;
301 if (soutopt)
302 *soutopt=get_identityinfo(msg)->domain;
303
304 return AUTH_OK;
305 }
306
307 /* body of the incoming SIP message */
in_msgbody_proc(str * sout,str * soutopt,struct sip_msg * msg)308 static int in_msgbody_proc(str *sout, str *soutopt, struct sip_msg *msg)
309 {
310 if (!sout)
311 return AUTH_OK;
312
313 sout->s = get_body(msg);
314 if (!sout->s || sout->s[0] == 0) {
315 sout->len = 0;
316 } else {
317 if (!msg->content_length) {
318 LOG(L_ERR, "AUTH_IDENTITY:route_msgbody_proc: no Content-Length header found!\n");
319 return AUTH_ERROR;
320 }
321 sout->len = get_content_length(msg);
322 }
323
324 return AUTH_OK;
325 }
326
327 /* body of the outgoing SIP message */
out_msgbody_proc(str * sout,str * soutopt,struct sip_msg * msg)328 static int out_msgbody_proc(str *sout, str *soutopt, struct sip_msg *msg)
329 {
330
331 unsigned int len;
332 int err;
333 struct dest_info dst;
334 char scontentlen[AUTH_CONTENTLENGTH_LENGTH];
335
336
337 if (!sout)
338 return AUTH_OK;
339
340 #ifdef USE_DNS_FAILOVER
341 /* get info about outbound socket */
342 if ((uri2dst(NULL, &dst, msg, GET_NEXT_HOP(msg), PROTO_NONE) == 0)
343 #else
344 if ((uri2dst(&dst, msg, GET_NEXT_HOP(msg), PROTO_NONE) == 0)
345 #endif
346 || (dst.send_sock == 0)) {
347 LOG(L_ERR, "AUTH_IDENTITY:rtend_msgbody_proc: Can't determinate destination socket\n");
348 return -1;
349 }
350
351 /* we save it to global variable too to be able to free it later */
352 sout->s = glb_msgbody = build_body(msg, &len, &err, &dst);
353 if (err) {
354 LOG(L_ERR, "AUTH_IDENTITY:rtend_msgbody_proc: Can't build body (%d)\n", err);
355 return -2;
356 }
357
358 sout->len = (int)len;
359
360 /* authentication services MUST add a Content-Length header field to
361 * SIP requests if one is not already present
362 *
363 * content-length (if present) must be already parsed and if destination
364 * protocol is not UDP then core will append Content-Length
365 */
366 if (!msg->content_length && dst.proto==PROTO_UDP) {
367 snprintf(scontentlen, sizeof(scontentlen), "Content-Length: %d\r\n", len);
368 scontentlen[sizeof(scontentlen)-1]=0;
369 /* if HDR_CONTENTLENGTH_T's specified then the header won't be added! */
370 if (append_hf(msg, scontentlen, HDR_OTHER_T)) {
371 pkg_free(glb_msgbody);
372 glb_msgbody=NULL;
373 return -3;
374 }
375 }
376
377 return AUTH_OK;
378 }
379
380 /* Contact header deinitializer of outgoing message */
free_out_contacthdr(void)381 static void free_out_contacthdr(void)
382 {
383 void** h_parsed;
384
385 h_parsed=&glb_contact.parsed; /*strict aliasing warnings workarround */
386 if (glb_siphdr) {
387 pkg_free(glb_siphdr);
388 glb_siphdr=NULL;
389 }
390
391 if (glb_contact.parsed)
392 free_contact((contact_body_t**)h_parsed);
393 }
394
395 /* body deinitializer of the outgoing message */
free_out_msgbody(void)396 static void free_out_msgbody(void)
397 {
398 if (glb_msgbody) {
399 pkg_free(glb_msgbody);
400 glb_msgbody=NULL;
401 }
402 }
403
404 /* Digest-string assebmler function (RFC 4474 [9] */
digeststr_asm(dynstr * sout,struct sip_msg * msg,str * sdate,int iflags)405 int digeststr_asm(dynstr *sout, struct sip_msg *msg, str *sdate, int iflags)
406 {
407 /* incoming SIP message parser describer */
408 dgst_part incoming_sip_digest_desc[] = {
409 { DS_FROM, fromhdr_proc, NULL, DS_REQUIRED },
410 { DS_TO, tohdr_proc, NULL, DS_REQUIRED },
411 { DS_CALLID, callidhdr_proc, NULL, DS_REQUIRED },
412 { DS_CSEQ, cseqhdr_proc, NULL, DS_REQUIRED },
413 { DS_DATE, datehdr_proc, NULL, DS_NOTREQUIRED },
414 { DS_CONTACT, in_contacthdr_proc, NULL, DS_NOTREQUIRED },
415 { DS_BODY, in_msgbody_proc, NULL, DS_NOTREQUIRED },
416 { 0, NULL, NULL, 0 }
417 };
418 /* outgoing SIP message parser describer */
419 dgst_part outgoing_sip_digest_desc[] = {
420 { DS_FROM, fromhdr_proc, NULL, DS_REQUIRED },
421 { DS_TO, tohdr_proc, NULL, DS_REQUIRED },
422 { DS_CALLID, callidhdr_proc, NULL, DS_REQUIRED },
423 { DS_CSEQ, cseqhdr_proc, NULL, DS_REQUIRED },
424 { DS_DATE, datehdr_proc, NULL, DS_NOTREQUIRED },
425 { DS_CONTACT, out_contacthdr_proc, free_out_contacthdr, DS_NOTREQUIRED },
426 { DS_BODY, out_msgbody_proc, free_out_msgbody, DS_NOTREQUIRED },
427 { 0, NULL, NULL, 0 }
428 };
429 dgst_part *pactpart;
430 dgst_part *sip_digest_desc;
431 str sact, sactopt;
432 int i1;
433 int iRes;
434
435
436 if ((iflags & AUTH_INCOMING_BODY) ^ (iflags & AUTH_OUTGOING_BODY)) {
437 (iflags & AUTH_INCOMING_BODY) ?
438 (sip_digest_desc = incoming_sip_digest_desc) :
439 (sip_digest_desc = outgoing_sip_digest_desc);
440 } else
441 /* AUTH_INCOMING_BODY or AUTH_OUTGOING_BODY flag must set */
442 return -1;
443
444 resetstr_dynstr(sout);
445
446 for (pactpart=&sip_digest_desc[0],i1=0; pactpart[i1].itype; i1++) {
447 iRes=pactpart[i1].pfunc(&sact, &sactopt, msg);
448
449 /* there was an error or the required header is missing */
450 if (iRes==AUTH_ERROR
451 || (iRes==AUTH_NOTFOUND && (pactpart[i1].iflag & DS_REQUIRED)))
452 return -1;
453
454 switch (pactpart[i1].itype) {
455 /* Cseq handle (we need SP instead of LWS (RFC4474 [9])) */
456 case DS_CSEQ:
457 if (app2dynstr(sout,&sact))
458 return -1;
459 if (app2dynchr(sout,' '))
460 return -2;
461 if (app2dynstr(sout,&sactopt))
462 return -3;
463 break;
464 case DS_DATE:
465 if (iRes==AUTH_NOTFOUND) {
466 if (iflags & AUTH_ADD_DATE) {
467 if (app2dynstr(sout,sdate))
468 return -8;
469 } else {
470 /* Date header must exist */
471 LOG(L_ERR, "AUTH_IDENTITY:digeststr_asm: DATE header is not found\n");
472 return -9;
473 }
474 break;
475 }
476 if (app2dynstr(sout,&sact))
477 return -10;
478 break;
479 default:
480 if (iRes==AUTH_NOTFOUND)
481 break;
482 if (app2dynstr(sout,&sact))
483 return -10;
484 }
485
486 /* if there is desctructor function available then we call it */
487 if (pactpart[i1].pfreefunc)
488 pactpart[i1].pfreefunc();
489
490 /* we don't add separator after message body */
491 if (pactpart[i1+1].itype) {
492 /* we append the separator */
493 if (app2dynchr(sout,'|'))
494 return -11;
495 }
496 }
497
498 return 0;
499 }
500
501 /* copypasted and ripped from ser/modules/textops/textops.c) */
append_hf(struct sip_msg * msg,char * str1,enum _hdr_types_t type)502 int append_hf(struct sip_msg* msg, char *str1, enum _hdr_types_t type)
503 {
504 struct lump* anchor;
505 char* s;
506 int len;
507
508 if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
509 LOG(L_ERR, "AUTH_IDENTITY:append_hf: Error while parsing message\n");
510 return -1;
511 }
512
513 anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, type);
514 if (anchor == 0) {
515 LOG(L_ERR, "AUTH_IDENTITY:append_hf: Can't get anchor\n");
516 return -1;
517 }
518
519 len=strlen(str1);
520
521 s = (char*)pkg_malloc(len+1);
522 if (!s) {
523 LOG(L_ERR, "AUTH_IDENTITY:append_hf: No memory left\n");
524 return -1;
525 }
526
527 memcpy(s, str1, len);
528 s[len] = '\0';
529
530 if (insert_new_lump_before(anchor, s, len, type) == 0) {
531 LOG(L_ERR, "AUTH_IDENTITY:append_hf: Can't insert lump\n");
532 pkg_free(s);
533 return -1;
534 }
535 return 0;
536 }
537
538 /* get the current system date and appends it to the message */
append_date(str * sdate,int idatesize,time_t * tout,struct sip_msg * msg)539 int append_date(str *sdate, int idatesize, time_t *tout, struct sip_msg *msg)
540 {
541 char date_hf[AUTH_TIME_LENGTH];
542 char date_str[AUTH_TIME_LENGTH];
543 time_t tdate_now;
544 struct tm *bd_time;
545 size_t ilen;
546 int istrlen;
547
548
549 if ((tdate_now=time(0)) < 0) {
550 LOG(L_ERR, "AUTH_IDENTITY:append_date: time error %s\n", strerror(errno));
551 return -1;
552 }
553 if (!(bd_time=gmtime(&tdate_now))) {
554 LOG(L_ERR, "AUTH_IDENTITY:append_date: gmtime error\n");
555 return -2;
556 }
557
558 ilen=strftime(date_str, sizeof(date_str), AUTH_TIME_FORMAT, bd_time);
559 if (ilen >= sizeof(date_hf) - strlen("Date: \r\n.") || ilen==0) {
560 LOG(L_ERR, "AUTH_IDENTITY:append_date: unexpected time length\n");
561 return -3;
562 }
563
564 /* we append the date header to the message too */
565 istrlen=strlen("Date: ");
566 memcpy(date_hf,"Date: ",istrlen);
567 memcpy(date_hf+istrlen,date_str,ilen);
568 istrlen+=ilen;
569 date_hf[istrlen]='\r'; date_hf[istrlen+1]='\n'; date_hf[istrlen+2]=0;
570 if (append_hf(msg, date_hf, HDR_DATE_T))
571 return -4;
572
573 if (sdate && idatesize >= ilen) {
574 memcpy(sdate->s, date_str, ilen);
575 sdate->len=ilen;
576 } else {
577 return -5;
578 }
579
580 if (tout)
581 *tout=tdate_now;
582
583 return 0;
584 }
585
586 /*
587 *
588 * "Contact" header parser part
589 *
590 */
591
592
593 /* returns a pointer to the next line */
auth_next_line(char * buf,char * buf_end)594 static char *auth_next_line(char *buf, char *buf_end)
595 {
596 char *c;
597
598 c = buf;
599 do {
600 while ((c < buf_end) && (*c != '\n')) c++;
601 if (c < buf_end) c++;
602 if ((c < buf_end) && (*c == '\r')) c++;
603
604 } while ((c < buf_end) && ((*c == ' ') || (*c == '\t'))); /* next line begins with whitespace line folding */
605
606 return c;
607 }
608
609 /*
610 * Skip all white-chars and return position of the first
611 * non-white char
612 */
skip_ws(char * p,unsigned int size)613 static inline char* skip_ws(char* p, unsigned int size)
614 {
615 char* end;
616
617 end = p + size;
618 for(; p < end; p++) {
619 if ((*p != ' ') && (*p != '\t')) return p;
620 }
621 return p;
622 }
623
624 /* looks for "Contact" header */
auth_get_hf_name(char * begin,char * end,enum _hdr_types_t * type)625 static char *auth_get_hf_name(char *begin, char *end, enum _hdr_types_t *type)
626 {
627 char *p;
628 unsigned int val;
629
630
631 if (end - begin < 4) {
632 *type = HDR_ERROR_T;
633 return begin;
634 }
635
636 p = begin;
637 val = LOWER_DWORD(READ(p));
638
639 switch(val) {
640 case _cont_: /* Content-Length */
641 p+=4;
642 switch (LOWER_DWORD(READ(p))) {
643 case _act1_:
644 *type = HDR_CONTACT_T;
645 return (p + 4);
646 case _act2_:
647 *type = HDR_CONTACT_T;
648 p += 4;
649 goto dc_end;
650 }
651 *type = HDR_OTHER_T;
652 break;
653 default:
654 /* compact headers */
655 switch(LOWER_BYTE(*p)) {
656 case 'm':
657 switch(*(p + 1)) {
658 case ' ':
659 *type = HDR_CONTACT_T;
660 p += 2;
661 goto dc_end;
662 case ':':
663 *type = HDR_CONTACT_T;
664 return (p + 2);
665 }
666 *type = HDR_OTHER_T;
667 break;
668 default:
669 *type = HDR_OTHER_T;
670 break;
671 }
672 }
673
674 dc_end:
675 p = skip_ws(p, end - p);
676 if (*p != ':') {
677 goto other;
678 } else {
679 return (p + 1);
680 }
681
682 /* Unknown header type */
683 other:
684 p = q_memchr(p, ':', end - p);
685 if (!p) { /* No double colon found, error.. */
686 *type = HDR_ERROR_T;
687 return 0;
688 } else {
689 *type = HDR_OTHER_T;
690 return (p + 1);
691 }
692
693 return p;
694 }
695
696 /* parses buffer that contains a SIP message header, looks for "Contact"
697 * header field and returns the value of that */
get_contact_body(char * buf,unsigned int len,str * sout)698 static int get_contact_body(char *buf, unsigned int len, str *sout)
699 {
700 char *end, *s, *tmp, *match;
701 enum _hdr_types_t hf_type;
702
703
704 end = buf + len;
705 s = buf;
706
707 memset(sout, 0, sizeof(*sout));
708
709 while (s < end) {
710 if ((*s == '\n') || (*s == '\r')) {
711 /* end of SIP msg */
712 hf_type = HDR_EOH_T;
713 } else {
714 /* parse HF name */
715 if (!(s = auth_get_hf_name(s, end, &hf_type)))
716 return AUTH_ERROR;
717 }
718
719 switch(hf_type) {
720 case HDR_CONTACT_T:
721 tmp=eat_lws_end(s, end);
722 if (tmp>=end) {
723 LOG(L_ERR, "AUTH_IDENTITY:get_contact_body: get_hdr_field: HF empty\n");
724 return AUTH_ERROR;
725 }
726 sout->s=tmp;
727 /* find lf */
728 do{
729 match=q_memchr(tmp, '\n', end-tmp);
730 if (match){
731 match++;
732 }else {
733 LOG(L_ERR, "AUTH_IDENTITY:get_contact_body: bad msg body\n");
734 return AUTH_ERROR;
735 }
736 tmp=match;
737 } while( match<end &&( (*match==' ')||(*match=='\t') ) );
738 tmp=match;
739 sout->len=match-sout->s;
740 trim_r(*sout);
741 return AUTH_OK;
742 break;
743 case HDR_ERROR_T:
744 return AUTH_ERROR;
745 default:
746 s = auth_next_line(s, end);
747 }
748 }
749
750 return AUTH_NOTFOUND;
751 }
752