1 /*
2  * Copyright (c) 2007 iptelorg GmbH
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 /*!
22  * \file
23  * \brief Kamailio auth-identity :: Module interface
24  * \ingroup auth-identity
25  * Module: \ref auth-identity
26  */
27 
28 /*! \defgroup auth-identity Kamailio SIP identity support
29  *
30  * Auth Identity module provides functionalities for securely identifying
31  * originators of SIP messages. This module has two basic service:
32  *   - authorizer - authorizes a message and adds Identity and Identity-Info headers
33  *   - verifier - verifies an authorized message
34  *
35  */
36 
37 
38 #include <stdio.h>
39 #include <time.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 #include <openssl/pem.h>
44 #include <openssl/err.h>
45 #include <openssl/sha.h>
46 
47 #include <curl/curl.h>
48 #include <curl/easy.h>
49 
50 #include "../../core/dprint.h"
51 #include "../../core/ut.h"
52 #include "../../core/sr_module.h"
53 #include "../../core/mem/mem.h"
54 #include "../../core/parser/parse_from.h"
55 #include "../../core/parser/parse_cseq.h"
56 #include "../../core/parser/parse_content.h"
57 #include "../../core/parser/parse_uri.h"
58 #include "../../core/parser/contact/parse_contact.h"
59 #include "../../core/timer.h"
60 
61 #include "auth_identity.h"
62 
63 MODULE_VERSION;
64 
65 static int mod_init(void); /* Module initialization function */
66 static void mod_deinit(void);
67 static int add_identity(struct sip_msg* msg, char* srt1, char* str2);
68 static int get_certificate(struct sip_msg* msg, char* srt1, char* str2);
69 static int check_validity(struct sip_msg* msg, char* srt1, char* str2);
70 static int check_date(struct sip_msg* msg, char* srt1, char* str2);
71 static int check_callid(struct sip_msg* msg, char* srt1, char* str2);
72 static int date_proc(struct sip_msg* msg, char* srt1, char* str2);
73 static int check_certificate(struct sip_msg* msg, char* srt1, char* str2);
74 void callid_gc(unsigned int tick, void *param);
75 
76 /*
77  * Module parameter variables
78  */
79 char	*glb_sprivkeypath="";	/* private key of the authentication service */
80 char 	*glb_sservercerturl="";	/* URL of the certificate of the authentication service */
81 char 	*glb_sservercertpath=""; /* Path of the certificate of the authentication service */
82 int		glb_icertlimit=CERTIFICATE_TABLE_ITEM_LIMIT;
83 char	*glb_scainfo="";
84 int		glb_iauthval=AUTH_MSG_VALIDITY_TIME;	/* Message validity time in seconds (verification service)*/
85 int		glb_imsgtime=AUTH_MSG_TO_AUTH_VALIDITY_TIME;	/* Message validity time in seconds (authentication service)*/
86 int 	glb_icallidlimit=CALLID_TABLE_ITEM_LIMIT;
87 
88 CURL 	*glb_hcurl;		/* global cURL handle */
89 X509 	*glb_pcertx509=NULL;
90 X509_STORE *glb_cacerts=NULL;
91 
92 RSA 	*glb_hmyprivkey=NULL;	/* private key of the authentication service */
93 time_t	glb_imycertnotafter=0;
94 
95 int 	glb_authservice_disabled=0;
96 int 	glb_acceptpem=0;
97 
98 dynstr	glb_sdgst={{0,0},0}; /* Digest string */
99 dynstr	glb_sidentity={{0,0},0}; /* Identity message header */
100 dynstr	glb_sidentityinfo={{0,0},0}; /* Identity-info message header */
101 dynstr	glb_sdate={{0,0},0}; /* Date  message header */
102 
103 dynstr	glb_encedmsg={{0,0},0}; /* buffer for rsa encrypted string */
104 dynstr	glb_b64encedmsg={{0,0},0}; /* buffer for base64, rsa encrypted string */
105 
106 ttable *glb_tcert_table=0;				/* Certificate Table */
107 char glb_certisdownloaded=0;
108 tcert_item glb_tcert={{0,0},{0,0},0};	/* Actually Used Certificate */
109 
110 ttable *glb_tcallid_table=0;			/* Certificate Table */
111 typedef struct timeparams { /* sturct of the callid garbage collector */
112 	int ibnow;	/* the actual bucket we've not checked yet */
113 	int ibnum;  /* number of the buckets we've to check */
114 	int ibcir;  /* timer function's called this times during the whole table check */
115 } ttimeparams;
116 ttimeparams glb_ttimeparams={0,0,0};
117 
118 /*
119  * Exported functions
120  */
121 static cmd_export_t glb_cmds[] = {
122 	{"auth_date_proc", date_proc, 0, 0, 0, REQUEST_ROUTE},
123 	{"auth_add_identity", add_identity, 0, 0, 0, REQUEST_ROUTE},
124 	{"vrfy_get_certificate", get_certificate, 0, 0, 0, REQUEST_ROUTE},
125 	{"vrfy_check_msgvalidity", check_validity, 0, 0, 0, REQUEST_ROUTE},
126 	{"vrfy_check_certificate", check_certificate, 0, 0, 0, REQUEST_ROUTE},
127 	{"vrfy_check_date", check_date, 0, 0, 0, REQUEST_ROUTE},
128 	{"vrfy_check_callid", check_callid, 0, 0, 0, REQUEST_ROUTE},
129 	{0, 0, 0, 0, 0, 0}
130 };
131 
132 
133 /*
134  * Exported parameters
135  */
136 static param_export_t glb_params[] = {
137 	{"privatekey_path", 		PARAM_STRING,	&glb_sprivkeypath},
138 	{"certificate_url", 		PARAM_STRING,	&glb_sservercerturl},
139 	{"certificate_cache_limit", PARAM_INT, 		&glb_icertlimit},
140 	{"callid_cache_limit",		PARAM_INT, 		&glb_icallidlimit},
141 	{"certificate_path", 		PARAM_STRING,	&glb_sservercertpath},
142 	{"auth_validity_time",		PARAM_INT,    	&glb_iauthval},
143 	{"msg_timeout", 			PARAM_INT, 		&glb_imsgtime},
144 	{"cainfo_path", 			PARAM_STRING, 	&glb_scainfo},
145 	{"accept_pem_certs", 		PARAM_INT,		&glb_acceptpem},
146 	{0, 0, 0}
147 };
148 
149 
150 /*
151  * Module interface
152  */
153 struct module_exports exports = {
154 	"auth_identity",
155         DEFAULT_DLFLAGS, /* dlopen flags */
156 	glb_cmds,   /* Exported functions */
157 	glb_params, /* Exported parameters */
158 	0,          /* RPC methods */
159         0,          /* pseudo-variables exports */
160 	0,          /* response function */
161 	mod_init,   /* module initialization function */
162 	0,	    /* child initialization function */
163 	mod_deinit  /* destroy function */
164 };
165 
166 
mod_init(void)167 static int mod_init(void)
168 {
169 	CURLcode iRet;
170 	str sstr;
171 	FILE *hpemfile;
172 	char serr[160];
173 	X509 *pmycert=NULL;		/* certificate of the authentication service */
174 	time_t tnow, ttmp;
175 
176 	/*
177 	 *
178 	 * Parameter check
179 	 *
180 	 */
181 	if (glb_sprivkeypath[0]==0) {
182 		LOG(L_WARN, "AUTH_IDENTITY:mod_init: Private key path is missing! Authorization service is disabled\n");
183 		glb_authservice_disabled=1;
184 	}
185 	if (!glb_authservice_disabled && glb_sservercerturl[0]==0) {
186 		LOG(L_WARN, "AUTH_IDENTITY:mod_init: URL of certificate of the server is missing! Authorization service is disabled\n");
187 		glb_authservice_disabled=1;
188 	}
189 	if (!glb_authservice_disabled && glb_sservercertpath[0]==0) {
190 		LOG(L_WARN, "AUTH_IDENTITY:mod_init: Path of certificate of the server is missing! Authorization service is disabled\n");
191 		glb_authservice_disabled=1;
192 	}
193 
194 	/*
195 	 *
196 	 * Init the curl session and download buffer
197 	 *
198 	 */
199 	curl_global_init(CURL_GLOBAL_ALL);
200 	if ((glb_hcurl=curl_easy_init())==NULL) {
201 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: Unable to init cURL library!\n");
202 		return -1;
203 	}
204 	/* send all data to this function  */
205 	if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_WRITEFUNCTION, curlmem_cb))!=0) {
206 		LOG(L_ERR,
207 			"AUTH_IDENTITY:mod_init: Unable to set cURL write function option: %s\n",
208 			curl_easy_strerror(iRet));
209 		return -2;
210 	}
211 	/* we pass our 'glb_tcert' struct to the callback function */
212 	if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_WRITEDATA, (void *)(&glb_tcert.scertpem)))!=0) {
213 		LOG(L_ERR,
214 			"AUTH_IDENTITY:mod_init: Unable to set cURL writedata option: %s\n",
215 			curl_easy_strerror(iRet));
216 		return -4;
217 	}
218 	if (!(glb_tcert.scertpem.s=pkg_malloc(CERTIFICATE_LENGTH))) {
219 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: Not enough memory error\n");
220 		return -3;
221 	}
222   	/* some servers don't like requests that are made without a user-agent
223 	   field, so we provide one */
224 	if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_USERAGENT, NAME "-Agent/1.0"))!=0) {
225 		LOG(L_WARN,
226 			"AUTH_IDENTITY:mod_init: Unable to set cURL useragent option: %s\n",
227 			curl_easy_strerror(iRet));
228 	}
229 	if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_SSL_VERIFYPEER, 1))!=0) {
230 		LOG(L_WARN,
231 			"AUTH_IDENTITY:mod_init: Unable to set cURL verifypeer option: %s\n",
232 			curl_easy_strerror(iRet));
233 	}
234 	if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_SSL_VERIFYHOST, 2))!=0) {
235 		LOG(L_WARN,
236 			"AUTH_IDENTITY:mod_init: Unable to set cURL verifyhost option: %s\n",
237 			curl_easy_strerror(iRet));
238 	}
239 
240 	/* cainfo_path module parameter's been set */
241 	if (glb_scainfo[0]) {
242 		if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_CAINFO, glb_scainfo))!=0) {
243 			LOG(L_WARN,
244 				"AUTH_IDENTITY:mod_init: Unable to set cURL cainfo option: %s\n",
245 				curl_easy_strerror(iRet));
246 		}
247 	}
248 
249 
250 	/*
251 	 *
252 	 * OpenSSL certificate verification initialization
253 	 *
254 	 */
255 	OpenSSL_add_all_algorithms();
256 	if (!(glb_cacerts=X509_STORE_new())) {
257 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to initialize X509 store\n");
258 		return -16;
259 	}
260 	if (X509_STORE_set_default_paths(glb_cacerts)!=1) {
261 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to set X509 store default path\n");
262 		return -17;
263 	}
264 	if (glb_scainfo[0]
265 		   && X509_STORE_load_locations(glb_cacerts, glb_scainfo, NULL) != 1)
266 		LOG(L_WARN, "AUTH_IDENTITY:mod_init: unable to load X509 store location\n");
267 
268 
269 	/*
270 	 *
271 	 * Init the Date, Digest-String, Identity and Identity-Info
272 	 *
273 	 */
274 	if (initdynstr(&glb_sdgst, DGST_STR_INIT_SIZE))
275 		return -5;
276 
277 	/*
278 	 * Init certificate table
279 	 */
280 	if (init_table(&glb_tcert_table,
281 				   CERTIFICATE_TABLE_ENTRIES,
282 				   glb_icertlimit,
283 				   cert_item_cmp,
284 				   cert_item_init,
285 				   cert_item_least,
286 				   cert_item_free,
287 				   NULL))
288  		return -5;
289 
290 	/*
291 	 * Init call-id table
292 	 */
293 	if (init_table(&glb_tcallid_table,
294 				   CALLID_TABLE_ITEM_LIMIT,
295 				   glb_icallidlimit,
296 				   cid_item_cmp,
297 				   cid_item_init,
298 				   cid_item_least,
299 				   cid_item_free,
300 				   cid_item_gc))
301 		return -5;
302 
303 	glb_ttimeparams.ibnow=0;
304 	/* we've to check the whole table in glb_imsgtime, so the number of
305 	   buckets we've to check in every timer call is
306 	   CALLID_TABLE_ENTRIES/glb_imsgtime/CALLID_GARBAGE_COLLECTOR_INTERVAL */
307 	glb_ttimeparams.ibcir=glb_iauthval/CALLID_GARBAGE_COLLECTOR_INTERVAL;
308 	if (!glb_ttimeparams.ibcir)
309 		glb_ttimeparams.ibcir=1;
310 	glb_ttimeparams.ibnum=CALLID_TABLE_ENTRIES/glb_ttimeparams.ibcir;
311 
312 	if (register_timer(callid_gc, (void*)&glb_ttimeparams /* param*/, CALLID_GARBAGE_COLLECTOR_INTERVAL  /* period */) < 0 ) {
313 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: Can not register timer\n");
314 		return -5;
315 	}
316 
317 	/*
318 	 * If there were not enough parameter set then we could not initialize
319 	 * the authorizer part
320 	 */
321 	if (glb_authservice_disabled)
322 		return 0;
323 
324 
325 	if (initdynstr(&glb_sidentity, DGST_STR_INIT_SIZE))
326 		return -6;
327 
328 	if (initdynstr(&glb_sdate, AUTH_TIME_LENGTH))
329 		return -7;
330 
331 	if (initdynstr(&glb_sidentityinfo, AUTH_URL_LENGTH))
332 		return -8;
333 
334 	/* we initialize indentity info header */
335 	sstr.s=IDENTITY_INFO_FIRST_PART; sstr.len=strlen(IDENTITY_INFO_FIRST_PART);
336 	if (cpy2dynstr(&glb_sidentityinfo, &sstr))
337 		return -9;
338 	sstr.s=glb_sservercerturl; sstr.len=strlen(glb_sservercerturl);
339 	if (app2dynstr(&glb_sidentityinfo, &sstr))
340 		return -10;
341 	sstr.s=IDENTITY_INFO_LAST_PART;
342 	/* we copy the trailing \0 because append_hf expects strings */
343 	sstr.len=strlen(IDENTITY_INFO_LAST_PART) + 1;
344 	if (app2dynstr(&glb_sidentityinfo, &sstr))
345 		return -11;
346 
347 	/*
348   	 * Get my certificate
349 	 */
350 	if (!(hpemfile=fopen(glb_sservercertpath, "r"))) {
351 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to open certificate '%s'\n", strerror(errno));
352 		return -12;
353 	}
354 	if (!(pmycert=PEM_read_X509(hpemfile, NULL, NULL, NULL))) {
355 		ERR_error_string_n(ERR_get_error(), serr, sizeof serr);
356 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: '%s'\n", serr);
357 		fclose(hpemfile);
358 		return -13;
359 	}
360 	if (x509_get_notafter(&glb_imycertnotafter, pmycert)) {
361 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: Error getting certificate expiration date\n");
362 		return -13;
363 	}
364 	if (x509_get_notbefore(&ttmp, pmycert)) {
365 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: Error getting certificate validity date\n");
366 		return -13;
367 	}
368 	if ((tnow=time(0)) < 0) {
369 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: time error %s\n", strerror(errno));
370 		return -13;
371 	}
372 	if (tnow < ttmp || tnow > glb_imycertnotafter) {
373 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: Date of certificate is invalid (%s)\n", glb_sservercertpath);
374 		return -14;
375 	}
376 
377 	if (fclose(hpemfile))
378 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to close file\n");
379 	X509_free(pmycert);
380 
381 	/*
382 	 *
383  	 * Init RSA-SHA1 encoder
384 	 *
385 	 */
386 	hpemfile=fopen(glb_sprivkeypath, "r");
387 	if (!hpemfile)
388 	{
389 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to open private key '%s'\n", strerror(errno));
390 		return -12;
391 	}
392 	glb_hmyprivkey=PEM_read_RSAPrivateKey(hpemfile, NULL, NULL, NULL);
393 	if (!glb_hmyprivkey)
394 	{
395 		ERR_error_string_n(ERR_get_error(), serr, sizeof serr);
396 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: '%s'\n", serr);
397 		fclose(hpemfile);
398 		return -13;
399 	}
400 	if (fclose(hpemfile))
401 		LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to close file\n");
402 
403 	/* we encrypt the digest string hash to this buffer */
404 	if (initdynstr(&glb_encedmsg, RSA_size(glb_hmyprivkey)))
405 		return -14;
406 
407 	/* we base64 encode the encrypted digest string hash to this buffer */
408 	if (initdynstr(&glb_b64encedmsg, (RSA_size(glb_hmyprivkey)/3+1)*4))
409 		return -15;
410 
411 	return 0;
412 }
413 
414 
mod_deinit(void)415 static void mod_deinit(void)
416 {
417 	curl_easy_cleanup(glb_hcurl);
418 	if (glb_tcert.scertpem.s)
419 		pkg_free(glb_tcert.scertpem.s);
420 	free_dynstr(&glb_sdgst);
421 	free_dynstr(&glb_sidentity);
422 	free_dynstr(&glb_sdate);
423  	free_table(glb_tcert_table);
424 	free_table(glb_tcallid_table);
425 
426 	if (glb_cacerts)
427 		X509_STORE_free(glb_cacerts);
428 }
429 
430 
431 /*
432  *
433  *	VERIFIER FUNCTIONS
434  *
435  */
436 
437 
get_certificate(struct sip_msg * msg,char * srt1,char * str2)438 static int get_certificate(struct sip_msg* msg, char* srt1, char* str2)
439 {
440 	if (identityinfohdr_proc(&glb_tcert.surl, NULL, msg))
441 		return -3;
442 
443 	/* we support rsa-sha1 only (alg.len==0 then we use rsa-sha1) */
444 	if (get_identityinfo(msg)->alg.len
445 		&& (get_identityinfo(msg)->alg.len != strlen("rsa-sha1")
446 		    || strncasecmp("rsa-sha1",
447 							get_identityinfo(msg)->alg.s,
448 							get_identityinfo(msg)->alg.len ))) {
449 		LOG(L_ERR, "AUTH_IDENTITY:get_certificate: Unsupported Identity-Info algorithm\n");
450 		return -5;
451 	}
452 
453 	/* this case ivalidbefore==0 singns that this certificate was downloaded */
454 	glb_tcert.ivalidbefore=0;
455 
456 	/* chech whether this certificate is our certificate table */
457 	if (get_cert_from_table(glb_tcert_table, &glb_tcert.surl, &glb_tcert)) {
458 		/* we did not found it in the table, so we've to download it */
459 		/* we reset the PEM buffer */
460 		glb_tcert.scertpem.len=0;
461 		if (download_cer(&glb_tcert.surl, glb_hcurl))
462 			return -6;
463 		glb_certisdownloaded=1;
464 	} else
465 		glb_certisdownloaded=0;
466 
467 	if (retrieve_x509(&glb_pcertx509, &glb_tcert.scertpem, glb_acceptpem))
468 		return -7;
469 
470 
471 	return 1;
472 }
473 
474 /*
475  * If the digest-string, assembled from the message, corresponds to the string
476  * decoded from the Identity header by the acquired public key then the message
477  * is valid. RFC 4474 [6] Step 3
478  */
check_validity(struct sip_msg * msg,char * srt1,char * str2)479 static int check_validity(struct sip_msg* msg, char* srt1, char* str2)
480 {
481 	str sidentity;
482 	char sencedsha[HASH_STR_SIZE];
483 	int iencedshalen;
484 #ifndef NEW_RSA_PROC
485 	char ssha[HASH_STR_SIZE];
486 #endif
487 	int ishalen;
488 	unsigned char sstrcrypted[SHA_DIGEST_LENGTH];
489 	int iRet=1;
490 
491 
492 	if (!glb_pcertx509) {
493 		LOG(L_ERR, "AUTH_IDENTITY:check_validity: Certificate uninitialized! (has vrfy_get_certificate been called?)\n");
494 		return -1;
495 	}
496 
497 	do {
498 		/* get the value of identity header parsed */
499 		if (identityhdr_proc(&sidentity, NULL, msg)) {
500 			iRet=-1;
501 			break;
502 		}
503 
504 		/* the length of identity value should be 172 octets long */
505 		if (sidentity.len > sizeof(sencedsha)) {
506 			LOG(L_ERR, "AUTH_IDENTITY:check_validity: Unexpected Identity length (%d)\n", sidentity.len);
507 			iRet=-2;
508 			break;
509 		}
510 
511 		/* base64 decode the value of Identity header */
512 		base64decode(sidentity.s, sidentity.len, sencedsha, &iencedshalen);
513 
514 		/* assemble the digest string to be able to compare it with decrypted one */
515 		if (digeststr_asm(&glb_sdgst, msg, NULL, AUTH_INCOMING_BODY)) {
516 			iRet=-5;
517 			break;
518 		}
519 		/* calculate hash */
520 		SHA1((unsigned char*)getstr_dynstr(&glb_sdgst).s,
521 			  getstr_dynstr(&glb_sdgst).len,
522 			  sstrcrypted);
523 
524 #ifdef NEW_RSA_PROC
525 		/* decrypt with public key retrieved from the downloaded certificate
526 		   and compare it with the calculated digest hash */
527 		if (rsa_sha1_dec(sencedsha, iencedshalen,
528 						 (char *)sstrcrypted, sizeof(sstrcrypted), &ishalen,
529 						 glb_pcertx509)) {
530 			iRet=-3;
531 			break;
532 		} else
533 			LOG(AUTH_DBG_LEVEL, "AUTH_IDENTITY VERIFIER: Identity OK\n");
534 #else
535 		/* decrypt with public key retrieved from the downloaded certificate */
536 		if (rsa_sha1_dec(sencedsha, iencedshalen,
537 						 ssha, sizeof(ssha), &ishalen,
538 						 glb_pcertx509)) {
539 			iRet=-3;
540 			break;
541 		}
542 
543 		/* check size */
544 		if (ishalen != sizeof(sstrcrypted)) {
545 			LOG(L_ERR, "AUTH_IDENTITY:check_validity: Unexpected decrypted hash length (%d != %d)\n", ishalen, SHA_DIGEST_LENGTH);
546 			iRet=-4;
547 			break;
548 		}
549 		/* compare */
550 		if (memcmp(sstrcrypted, ssha, ishalen)) {
551 			LOG(L_INFO, "AUTH_IDENTITY VERIFIER: comparing hashes failed -> Invalid Identity Header\n");
552 			iRet=-6;
553 			break;
554 		} else
555 			LOG(AUTH_DBG_LEVEL, "AUTH_IDENTITY VERIFIER: Identity OK\n");
556 #endif
557 	} while (0);
558 
559 	glb_pcertx509=NULL;
560 
561 	return iRet;
562 }
563 
564 /*
565  * The Date header must indicate a time within 3600 seconds of the receipt of a
566  * message. RFC 4474 [6] Step 4
567  */
check_date(struct sip_msg * msg,char * srt1,char * str2)568 static int check_date(struct sip_msg* msg, char* srt1, char* str2)
569 {
570 	time_t tnow, tmsg;
571 	int ires;
572 
573 	ires=datehdr_proc(NULL, NULL, msg);
574 	if (ires)
575 		return -1;
576 
577 
578 #ifdef HAVE_TIMEGM
579 	tmsg=timegm(&get_date(msg)->date);
580 #else
581 	tmsg=_timegm(&get_date(msg)->date);
582 #endif
583 	if (tmsg < 0) {
584 		LOG(L_ERR, "AUTH_IDENTITY:check_date: timegm error\n");
585 		return -2;
586 	}
587 
588 	if ((tnow=time(0)) < 0) {
589 		LOG(L_ERR, "AUTH_IDENTITY:check_date: time error %s\n", strerror(errno));
590 		return -3;
591 	}
592 
593 	if (tnow > tmsg + glb_iauthval) {
594 		LOG(L_INFO, "AUTH_IDENTITY VERIFIER: Outdated date header value (%ld sec)\n", tnow - tmsg + glb_iauthval);
595 		return -4;
596 	} else
597 		LOG(AUTH_DBG_LEVEL, "AUTH_IDENTITY VERIFIER: Date header value OK\n");
598 
599 	return 1;
600 }
601 
602 
check_certificate(struct sip_msg * msg,char * srt1,char * str2)603 int check_certificate(struct sip_msg* msg, char* srt1, char* str2) {
604 	struct sip_uri tfrom_uri;
605 	str suri;
606 
607 	if (!glb_pcertx509) {
608 		LOG(L_ERR, "AUTH_IDENTITY:check_certificate: Certificate uninitialized! (has vrfy_get_certificate been called?)\n");
609 		return -1;
610 	}
611 	/* this certificate was downloaded so we've to verify and add it to table */
612 	if (glb_certisdownloaded) {
613 		if (fromhdr_proc(&suri, NULL, msg))
614 			return -1;
615 
616 		if (parse_uri(suri.s, suri.len, &tfrom_uri)) {
617 			LOG(L_ERR, "AUTH_IDENTITY:get_certificate: Error while parsing FROM URI\n");
618 			return -2;
619 		}
620 
621 		if (verify_x509(glb_pcertx509, glb_cacerts))
622 			return -3;
623 
624 		if (check_x509_subj(glb_pcertx509, &tfrom_uri.host))
625 			return -4;
626 
627 		/* we retrieve expiration date from the certificate (it needs for
628 		   certificate table garbage collector) */
629 		if (x509_get_notafter(&glb_tcert.ivalidbefore, glb_pcertx509))
630 			return -5;
631 
632 		if (addcert2table(glb_tcert_table, &glb_tcert))
633 			return -6;
634 	}
635 	return 1;
636 }
637 
check_callid(struct sip_msg * msg,char * srt1,char * str2)638 static int check_callid(struct sip_msg* msg, char* srt1, char* str2)
639 {
640 	str scid, sftag, scseqnum;
641 	unsigned int ucseq;
642 	int ires;
643 	time_t ivalidbefore;
644 
645 
646 	if (callidhdr_proc(&scid, NULL, msg))
647 		return -1;
648 
649 	if (cseqhdr_proc(&scseqnum, NULL, msg))
650 		return -2;
651 	if (str2int(&scseqnum, &ucseq))
652 		return -3;
653 
654 	if (fromhdr_proc(NULL, &sftag, msg))
655 		return -4;
656 
657 	if ((ivalidbefore=time(0)) < 0) {
658 		LOG(L_ERR, "AUTH_IDENTITY:check_callid: time error %s\n", strerror(errno));
659 		return -5;
660 	}
661 
662 	ires=proc_cid(glb_tcallid_table,
663 				  &scid,
664 				  &sftag,
665 				  ucseq,
666 				  ivalidbefore + glb_iauthval);
667 	if (ires) {
668 		if (ires==AUTH_FOUND)
669 			LOG(L_INFO, "AUTH_IDENTITY VERIFIER: Call is replayed!\n");
670 		return -6;
671 	}
672 
673 	return 1;
674 }
675 
676 
callid_gc(unsigned int tick,void * param)677 void callid_gc(unsigned int tick, void *param)
678 {
679 	/* check the last slice */
680 	if (((ttimeparams*)param)->ibnow + 1 == ((ttimeparams*)param)->ibcir) {
681 		garbage_collect(glb_tcallid_table,
682 						 (((ttimeparams*)param)->ibnow)*((ttimeparams*)param)->ibnum,
683 						 CALLID_TABLE_ENTRIES-1);
684 		/* we step to the first slice */
685 		((ttimeparams*)param)->ibnow=0;
686 	} else {
687 		garbage_collect(glb_tcallid_table,
688 						 (((ttimeparams*)param)->ibnow)*((ttimeparams*)param)->ibnum,
689 						 ((((ttimeparams*)param)->ibnow+1)*((ttimeparams*)param)->ibnum)-1);
690 		/* we step to the next slice */
691 		((ttimeparams*)param)->ibnow++;
692 	}
693 }
694 
695 /*
696  *
697  *	AUTHORIZER FUNCTIONS
698  *
699  */
700 
701 /* Checks the Date header of the message. RFC4474 [5] Step 3 */
date_proc(struct sip_msg * msg,char * srt1,char * str2)702 static int date_proc(struct sip_msg* msg, char* srt1, char* str2)
703 {
704 	str sdate;
705 	int iRes;
706 	time_t tmsg, tnow;
707 
708 	if (glb_authservice_disabled) {
709 		LOG(L_WARN, "AUTH_IDENTITY:date_proc: Authentication Service is disabled\n");
710 		return -1;
711 	}
712 
713 	getstr_dynstr(&glb_sdate).len=0;
714 
715 	/* we'd like to get the DATE header of the massage */
716 	iRes=datehdr_proc(&sdate, NULL, msg);
717 	switch (iRes) {
718 		case AUTH_ERROR:
719 			return -1;
720 		case AUTH_NOTFOUND:
721 			if (append_date(&getstr_dynstr(&glb_sdate), glb_sdate.size, &tmsg, msg))
722 				return -2;
723 			break;
724 		/* Message has Date header so we check that */
725 		case AUTH_OK:
726 #ifdef HAVE_TIMEGM
727 			tmsg=timegm(&get_date(msg)->date);
728 #else
729 			tmsg=_timegm(&get_date(msg)->date);
730 #endif
731 			if (tmsg < 0) {
732 				LOG(L_ERR, "AUTH_IDENTITY:date_proc: timegm error\n");
733 				return -3;
734 			}
735 			if ((tnow=time(NULL))<0) {
736 				LOG(L_ERR, "AUTH_IDENTITY:date_proc: time error\n");
737 				return -4;
738 			}
739 			/*
740 			 * If the value of this field contains a time different by more than
741 			 * ten minutes from the current time noted by the authentication
742 			 * service then it should reject the message.
743 			 */
744 			if (tmsg + glb_imsgtime < tnow || tnow + glb_imsgtime < tmsg) {
745 				LOG(L_INFO, "AUTH_IDENTITY AUTHORIZER: Date header overdue\n");
746 				return -6;
747 			}
748 			break;
749 		default:
750 			/* unknown result */
751 			return -7;
752 	}
753 
754 	/*
755 	 * The authentication service MUST verify that the Date header
756 	 * falls within the validity period of its certificate
757 	 * RFC 4474 [6] Step 3
758 	 */
759 	if (glb_imycertnotafter < tmsg) {
760 		LOG(L_INFO, "AUTH_IDENTITY AUTHORIZER: My certificate has been expired\n");
761 		return -8;
762 	}
763 
764 	return 1;
765 }
766 
767 /*
768  * Concates the message From, To, Call-ID, Cseq, Date,  Contact header fields
769  * and the message body to digest-string, signs with the domain private-key,
770  * BASE64 encodes that, and finally adds it to the message as the 'Identity'
771  * header value. RFC4474 [5] Step 4
772  *
773  * Adds Identity-Info header to the message which contains an URI from which
774  * its certificate can be acquired. RFC4474 [5] Step 4
775  */
add_identity(struct sip_msg * msg,char * srt1,char * str2)776 static int add_identity(struct sip_msg* msg, char* srt1, char* str2)
777 {
778 	int iRes;
779 	str sstr;
780 
781 
782 	if (glb_authservice_disabled) {
783 		LOG(L_WARN, "AUTH_IDENTITY:add_identity: Authentication Service is disabled\n");
784 		return -1;
785 	}
786 
787 	/* check Date */
788 	iRes=datehdr_proc(NULL, NULL, msg);
789 	switch (iRes) {
790  		case AUTH_ERROR:
791 			return -1;
792 		case AUTH_NOTFOUND:
793 			if (!getstr_dynstr(&glb_sdate).len) {
794 				/*
795 				 * date_proc() must be called before add_identity() because
796 				 * that function initializes the Date if that not exists
797 				 * in the SIP message
798 				 */
799 				LOG(L_ERR, "AUTH_IDENTITY:add_identity: Date header is not found (has auth_date_proc been called?)\n");
800 				return -2;
801 			}
802 			/*  assemble the digest string and the DATE header is missing in the orignal message */
803 			if (digeststr_asm(&glb_sdgst,
804 							  msg,
805 							  &getstr_dynstr(&glb_sdate),
806 							  AUTH_OUTGOING_BODY | AUTH_ADD_DATE))
807 				return -3;
808 			break;
809 		default:
810 			/*  assemble the digest string and the DATE header is available in the message */
811 			if (digeststr_asm(&glb_sdgst, msg, NULL, AUTH_OUTGOING_BODY))
812 				return -4;
813 			break;
814 	}
815 
816 	/* calculate the SHA1 hash and encrypt with our provate key */
817 	if (rsa_sha1_enc(&glb_sdgst, &glb_encedmsg, &glb_b64encedmsg, glb_hmyprivkey))
818 		return -5;
819 
820 	/* we assemble the value of the Identity haader */
821 	sstr.s=IDENTITY_FIRST_PART; sstr.len=strlen(IDENTITY_FIRST_PART);
822 	if (cpy2dynstr(&glb_sidentity, &sstr))
823 		return -6;
824 
825 	if (app2dynstr(&glb_sidentity, &getstr_dynstr(&glb_b64encedmsg)))
826 		return -7;
827 
828 	sstr.s=IDENTITY_LAST_PART;
829 	/* +1 : we need the trailing \0 character too */
830 	sstr.len=strlen(IDENTITY_LAST_PART) + 1;
831 	if (app2dynstr(&glb_sidentity, &sstr))
832 		return -8;
833 
834 	if (append_hf(msg, getstr_dynstr(&glb_sidentity).s, HDR_IDENTITY_T))
835 		return -9;
836 
837 	if (append_hf(msg, getstr_dynstr(&glb_sidentityinfo).s, HDR_IDENTITY_INFO_T))
838 		return -10;
839 
840 	return 1;
841 }
842