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