Browse code

stirshaken: Add PVs to allow access to x509 subject and ppt grants

- added vs_certsubject_pvname and vs_pptgrants_pvname config params
- adjusted log level of load/unload events

Trevor Peirce authored on 23/03/2022 02:53:54 • Daniel-Constantin Mierla committed on 25/03/2022 12:12:37
Showing 2 changed files
... ...
@@ -253,6 +253,47 @@ modparam("stirshaken", "vs_cache_dir", "/tmp/cert_cache")
253 253
 ...
254 254
 modparam("stirshaken", "vs_cache_expire_s", 15)
255 255
 ...
256
+</programlisting>
257
+		</example>
258
+	</section>
259
+		<section>
260
+		<title><varname>vs_certsubject_pvname</varname> (str)</title>
261
+		<para>
262
+		If vs_certsubject_pvname is set then the Subject of the authenticated x509 certificate will be written to this pseudo-variable when
263
+		stirshaken_check_identity() is executed.  If the Identity header cannot be fully authenticated the pseudo-variable will be set to $null.
264
+		</para>
265
+		<para>
266
+		<emphasis>
267
+			Default value is blank (disabled).
268
+		</emphasis>
269
+		</para>
270
+		<example>
271
+		<title>Set <varname>vs_certsubject_pvname</varname> parameter</title>
272
+		<programlisting format="linespecific">
273
+...
274
+modparam("stirshaken", "vs_certsubject_pvname", "$vn(certsubject)")
275
+...
276
+</programlisting>
277
+		</example>
278
+	</section>
279
+		</section>
280
+		<section>
281
+		<title><varname>vs_pptgrants_pvname</varname> (str)</title>
282
+		<para>
283
+		If vs_pptgrants_pvname is set then the JSON string of the authenticated PASSporT's grants will be written to this pseudo-variable when
284
+		stirshaken_check_identity() is executed.  If the Identity header cannot be fully authenticated the pseudo-variable will be set to $null.
285
+		</para>
286
+		<para>
287
+		<emphasis>
288
+			Default value is blank (disabled).
289
+		</emphasis>
290
+		</para>
291
+		<example>
292
+		<title>Set <varname>vs_pptgrants_pvname</varname> parameter</title>
293
+		<programlisting format="linespecific">
294
+...
295
+modparam("stirshaken", "vs_pptgrants_pvname", "$vn(grants)")
296
+...
256 297
 </programlisting>
257 298
 		</example>
258 299
 	</section>
... ...
@@ -50,6 +50,11 @@ static int stirshaken_vs_cache_certificates = 0;
50 50
 static size_t stirshaken_vs_cache_expire_s = 120;
51 51
 static str stirshaken_vs_cache_dir = str_init("");
52 52
 
53
+static str stirshaken_vs_x509_pvname = STR_NULL;
54
+static pv_spec_t stirshaken_vs_x509_pv;
55
+static str stirshaken_vs_pptg_pvname = STR_NULL;
56
+static pv_spec_t stirshaken_vs_pptg_pv;
57
+
53 58
 static int mod_init(void);
54 59
 static int child_init(int);
55 60
 static void mod_destroy(void);
... ...
@@ -90,6 +95,8 @@ static param_export_t params[] = {
90 95
 	{"vs_cache_certificates",	PARAM_INT,   &stirshaken_vs_cache_certificates},
91 96
 	{"vs_cache_expire_s",		PARAM_INT,   &stirshaken_vs_cache_expire_s},
92 97
 	{"vs_cache_dir",			PARAM_STR,   &stirshaken_vs_cache_dir},
98
+	{"vs_certsubject_pvname",   PARAM_STR,   &stirshaken_vs_x509_pvname},
99
+	{"vs_pptgrants_pvname",     PARAM_STR,   &stirshaken_vs_pptg_pvname},
93 100
 	{0, 0, 0}
94 101
 };
95 102
 
... ...
@@ -356,6 +363,22 @@ static int mod_init(void)
356 363
 				"then please set @vs_verify_x509_cert_path param to 1 and configure @vs_ca_dir (and optionally @vs_crl_dir)\n");
357 364
 	}
358 365
 
366
+	if(stirshaken_vs_pptg_pvname.s != 0) {
367
+		if(pv_parse_spec(&stirshaken_vs_pptg_pvname, &stirshaken_vs_pptg_pv) == NULL
368
+				|| !pv_is_w(&stirshaken_vs_pptg_pv)) {
369
+			LM_ERR("Invalid vs_pptgrants_pvname '%s'\n", stirshaken_vs_pptg_pvname.s);
370
+			return -1;
371
+		}
372
+	}
373
+
374
+	if(stirshaken_vs_x509_pvname.s != 0) {
375
+		if(pv_parse_spec(&stirshaken_vs_x509_pvname, &stirshaken_vs_x509_pv) == NULL
376
+				|| !pv_is_w(&stirshaken_vs_x509_pv)) {
377
+			LM_ERR("Invalid vs_certsubject_pvname '%s'\n", stirshaken_vs_x509_pvname.s);
378
+			return -1;
379
+		}
380
+	}
381
+
359 382
 	return 0;
360 383
 }
361 384
 
... ...
@@ -364,13 +387,13 @@ static int mod_init(void)
364 387
  */
365 388
 static int child_init(int rank)
366 389
 {
367
-	LM_INFO("mod stirshaken child init\n");
390
+	LM_DBG("mod stirshaken child init\n");
368 391
 	return 0;
369 392
 }
370 393
 
371 394
 static void mod_destroy(void)
372 395
 {
373
-	LM_INFO("mod stirshaken destroy\n");
396
+	LM_DBG("mod stirshaken destroy\n");
374 397
 	stir_shaken_as_destroy(&as);
375 398
 	stir_shaken_vs_destroy(&vs);
376 399
 	stir_shaken_deinit();
... ...
@@ -391,7 +414,7 @@ static int stirshaken_handle_cache(stir_shaken_context_t *ss, stir_shaken_passpo
391 414
 
392 415
 	if (!ss->cert_fetched_from_cache) {
393 416
 
394
-		// save certificate to cache with url as a key 
417
+		// save certificate to cache with url as a key
395 418
 		char cert_full_path[STIR_SHAKEN_BUFLEN] = { 0 };
396 419
 		const char *x5u = stir_shaken_passport_get_header(ss, passport, "x5u");
397 420
 
... ...
@@ -445,6 +468,8 @@ static int ki_stirshaken_check_identity(sip_msg_t *msg)
445 468
 	stir_shaken_passport_t *passport_out = NULL;
446 469
 	stir_shaken_cert_t *cert_out = NULL;
447 470
 
471
+	pv_value_t val;
472
+
448 473
 	for (hf = msg->headers; hf; hf = hf->next) {
449 474
 		if (hf->name.len == STIRSHAKEN_HDR_IDENTITY_LEN
450 475
 				&& strncasecmp(hf->name.s, STIRSHAKEN_HDR_IDENTITY,
... ...
@@ -503,6 +528,27 @@ static int ki_stirshaken_check_identity(sip_msg_t *msg)
503 528
 		}
504 529
 	}
505 530
 
531
+	if (stirshaken_vs_pptg_pvname.s != 0) {
532
+		memset(&val, 0, sizeof(pv_value_t));
533
+		val.flags = PV_VAL_STR;
534
+		val.rs.s = jwt_get_grants_json(passport_out->jwt, NULL);
535
+		val.rs.len = strlen(val.rs.s);
536
+		if (stirshaken_vs_pptg_pv.setf(msg, &stirshaken_vs_pptg_pv.pvp, (int)EQ_T, &val) < 0) {
537
+			LM_ERR("setting %s failed\n", stirshaken_vs_pptg_pvname.s);
538
+		}
539
+		stir_shaken_free_jwt_str(val.rs.s);
540
+	}
541
+
542
+	if (stirshaken_vs_x509_pvname.s != 0) {
543
+		memset(&val, 0, sizeof(pv_value_t));
544
+		val.flags = PV_VAL_STR;
545
+		val.rs.s = stir_shaken_cert_get_subject(cert_out);
546
+		val.rs.len = strlen(val.rs.s);
547
+		if (stirshaken_vs_x509_pv.setf(msg, &stirshaken_vs_x509_pv.pvp, (int)EQ_T, &val) < 0) {
548
+			LM_ERR("setting %s failed\n", stirshaken_vs_x509_pvname.s);
549
+		}
550
+	}
551
+
506 552
 	LM_DBG("identity check: ok (%s)\n", ss.x509_cert_path_checked ? "with X509 cert path check" : "without X509 cert path check");
507 553
 	stir_shaken_passport_destroy(&passport_out);
508 554
 	stir_shaken_cert_destroy(&cert_out);
... ...
@@ -512,6 +558,24 @@ fail:
512 558
 	stir_shaken_passport_destroy(&passport_out);
513 559
 	stir_shaken_cert_destroy(&cert_out);
514 560
 	LM_ERR("identity check: fail\n");
561
+	if (stirshaken_vs_pptg_pvname.s != 0) {
562
+		memset(&val, 0, sizeof(pv_value_t));
563
+		val.flags = PV_VAL_NULL;
564
+		//val.rs.s = NULL;
565
+		//val.rs.len = 0;
566
+		if (stirshaken_vs_pptg_pv.setf(msg, &stirshaken_vs_pptg_pv.pvp, (int)EQ_T, &val) < 0) {
567
+			LM_ERR("setting %s to null failed\n", stirshaken_vs_pptg_pvname.s);
568
+		}
569
+	}
570
+	if (stirshaken_vs_x509_pvname.s != 0) {
571
+		memset(&val, 0, sizeof(pv_value_t));
572
+		val.flags = PV_VAL_NULL;
573
+		//val.rs.s = NULL;
574
+		//val.rs.len = 0;
575
+		if (stirshaken_vs_x509_pv.setf(msg, &stirshaken_vs_x509_pv.pvp, (int)EQ_T, &val) < 0) {
576
+			LM_ERR("setting %s to null failed\n", stirshaken_vs_x509_pvname.s);
577
+		}
578
+	}
515 579
 	return -1;
516 580
 }
517 581
 
... ...
@@ -526,7 +590,7 @@ fail:
526 590
  * This method checks if PASSporT verifies successfully with a public key retrieved from obtained certificate.
527 591
  * Optionally (if Verification Service is configured to do so with stirshaken_vs_verify_x509_cert_path param set to 1)
528 592
  * this method checks if certificate is trusted, by execution of X509 certificate path check.
529
- * 
593
+ *
530 594
  * Optionally:
531 595
  * 		- retrieve PASSporT from SIP Identity Header
532 596
  * 		- retrieve certificate referenced in PASSporT's x5u header