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