mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-11-03 20:38:59 +00:00 
			
		
		
		
	res_stir_shaken: Allow sending Identity headers for unknown TNs
Added a new option "unknown_tn_attest_level" to allow Identity headers to be sent when a callerid TN isn't explicitly configured in stir_shaken.conf. Since there's no TN object, a private_key_file and public_cert_url must be configured in the attestation or profile objects. Since "unknown_tn_attest_level" uses the same enum as attest_level, some of the sorcery macros had to be refactored to allow sharing the enum and to/from string conversion functions. Also fixed a memory leak in crypto_utils:pem_file_cb(). Resolves: #921 UserNote: You can now set the "unknown_tn_attest_level" option in the attestation and/or profile objects in stir_shaken.conf to enable sending Identity headers for callerid TNs not explicitly configured.
This commit is contained in:
		
				
					committed by
					
						
						asterisk-org-access-app[bot]
					
				
			
			
				
	
			
			
			
						parent
						
							2694f78d03
						
					
				
				
					commit
					1646b78986
				
			@@ -99,6 +99,20 @@ One of "A", "B", "C"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Default: none
 | 
					Default: none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- unknown_tn_attest_level --------------------------------------------
 | 
				
			||||||
 | 
					Attestation level to use for unknown TNs.
 | 
				
			||||||
 | 
					One of "A", "B", "C"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Normally if a callerid TN isn't configured in stir_shaken.conf
 | 
				
			||||||
 | 
					no Identity header will be created. If this option is set,
 | 
				
			||||||
 | 
					however, an Identity header will be sent using this
 | 
				
			||||||
 | 
					attestation level.  Since there's no TN object, you must
 | 
				
			||||||
 | 
					ensure that a private_key_file and public_cert_url are
 | 
				
			||||||
 | 
					configured in the attestation or profile objects for
 | 
				
			||||||
 | 
					this to work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Default: none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- send_mky -----------------------------------------------------------
 | 
					-- send_mky -----------------------------------------------------------
 | 
				
			||||||
If set and an outgoing call uses DTLS, an "mky" Media Key grant will
 | 
					If set and an outgoing call uses DTLS, an "mky" Media Key grant will
 | 
				
			||||||
be added to the Identity header.  Although RFC8224/8225 require this,
 | 
					be added to the Identity header.  Although RFC8224/8225 require this,
 | 
				
			||||||
@@ -116,6 +130,7 @@ Example "attestation" object:
 | 
				
			|||||||
;private_key_file = /var/lib/asterisk/keys/stir_shaken/tns/multi-tns-key.pem
 | 
					;private_key_file = /var/lib/asterisk/keys/stir_shaken/tns/multi-tns-key.pem
 | 
				
			||||||
;public_cert_url = https://example.com/tncerts/multi-tns-cert.pem
 | 
					;public_cert_url = https://example.com/tncerts/multi-tns-cert.pem
 | 
				
			||||||
;attest_level = C
 | 
					;attest_level = C
 | 
				
			||||||
 | 
					;unknown_tn_attest_level = C
 | 
				
			||||||
 | 
					
 | 
				
			||||||
;--
 | 
					;--
 | 
				
			||||||
=======================================================================
 | 
					=======================================================================
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,9 +15,13 @@
 | 
				
			|||||||
 * the GNU General Public License Version 2. See the LICENSE file
 | 
					 * the GNU General Public License Version 2. See the LICENSE file
 | 
				
			||||||
 * at the top of the source tree.
 | 
					 * at the top of the source tree.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define _TRACE_PREFIX_ "ac",__LINE__, ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "asterisk.h"
 | 
					#include "asterisk.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "asterisk/cli.h"
 | 
					#include "asterisk/cli.h"
 | 
				
			||||||
 | 
					#include "asterisk/logger.h"
 | 
				
			||||||
#include "asterisk/sorcery.h"
 | 
					#include "asterisk/sorcery.h"
 | 
				
			||||||
#include "asterisk/paths.h"
 | 
					#include "asterisk/paths.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -31,6 +35,7 @@
 | 
				
			|||||||
#define DEFAULT_private_key_file NULL
 | 
					#define DEFAULT_private_key_file NULL
 | 
				
			||||||
#define DEFAULT_public_cert_url NULL
 | 
					#define DEFAULT_public_cert_url NULL
 | 
				
			||||||
#define DEFAULT_attest_level attest_level_NOT_SET
 | 
					#define DEFAULT_attest_level attest_level_NOT_SET
 | 
				
			||||||
 | 
					#define DEFAULT_unknown_tn_attest_level attest_level_NOT_SET
 | 
				
			||||||
#define DEFAULT_send_mky send_mky_NO
 | 
					#define DEFAULT_send_mky send_mky_NO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct attestation_cfg *empty_cfg = NULL;
 | 
					static struct attestation_cfg *empty_cfg = NULL;
 | 
				
			||||||
@@ -57,6 +62,9 @@ int as_is_config_loaded(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
generate_acfg_common_sorcery_handlers(attestation_cfg);
 | 
					generate_acfg_common_sorcery_handlers(attestation_cfg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					generate_sorcery_enum_from_str_ex(attestation_cfg,,unknown_tn_attest_level, attest_level, UNKNOWN);
 | 
				
			||||||
 | 
					generate_sorcery_enum_to_str_ex(attestation_cfg,,unknown_tn_attest_level, attest_level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void acfg_cleanup(struct attestation_cfg_common *acfg_common)
 | 
					void acfg_cleanup(struct attestation_cfg_common *acfg_common)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!acfg_common) {
 | 
						if (!acfg_common) {
 | 
				
			||||||
@@ -309,6 +317,9 @@ int as_config_load(void)
 | 
				
			|||||||
		DEFAULT_global_disable ? "yes" : "no",
 | 
							DEFAULT_global_disable ? "yes" : "no",
 | 
				
			||||||
		OPT_YESNO_T, 1, FLDSET(struct attestation_cfg, global_disable));
 | 
							OPT_YESNO_T, 1, FLDSET(struct attestation_cfg, global_disable));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum_option_register_ex(sorcery, CONFIG_TYPE, unknown_tn_attest_level,
 | 
				
			||||||
 | 
							unknown_tn_attest_level, attest_level,);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	register_common_attestation_fields(sorcery, attestation_cfg, CONFIG_TYPE,);
 | 
						register_common_attestation_fields(sorcery, attestation_cfg, CONFIG_TYPE,);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ast_sorcery_load_object(sorcery, CONFIG_TYPE);
 | 
						ast_sorcery_load_object(sorcery, CONFIG_TYPE);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,6 +116,12 @@ generate_enum_string_prototypes(attest_level,
 | 
				
			|||||||
	attest_level_C,
 | 
						attest_level_C,
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * unknown_tn_attest_level uses the same enum as attest_level.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum attest_level_enum unknown_tn_attest_level_from_str(const char *value);
 | 
				
			||||||
 | 
					const char *unknown_tn_attest_level_to_str(enum attest_level_enum value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * enum stir_shaken_failure_action is defined in
 | 
					 * enum stir_shaken_failure_action is defined in
 | 
				
			||||||
 * res_stir_shaken.h because res_pjsip_stir_shaken needs it
 | 
					 * res_stir_shaken.h because res_pjsip_stir_shaken needs it
 | 
				
			||||||
@@ -136,20 +142,23 @@ const char *stir_shaken_failure_action_to_str(
 | 
				
			|||||||
 * are _to_str and _from_str functions defined elsewhere.
 | 
					 * are _to_str and _from_str functions defined elsewhere.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define generate_sorcery_enum_to_str(__struct, __substruct, __lc_param) \
 | 
					#define generate_sorcery_enum_to_str_ex(__struct, __substruct, __lc_param, __base_enum) \
 | 
				
			||||||
static int sorcery_ ## __lc_param ## _to_str(const void *obj, const intptr_t *args, char **buf) \
 | 
					static int sorcery_ ## __lc_param ## _to_str(const void *obj, const intptr_t *args, char **buf) \
 | 
				
			||||||
{ \
 | 
					{ \
 | 
				
			||||||
	const struct __struct *cfg = obj; \
 | 
						const struct __struct *cfg = obj; \
 | 
				
			||||||
	*buf = ast_strdup(__lc_param ## _to_str(cfg->__substruct __lc_param)); \
 | 
						*buf = ast_strdup(__base_enum ## _to_str(cfg->__substruct __lc_param)); \
 | 
				
			||||||
	return *buf ? 0 : -1; \
 | 
						return *buf ? 0 : -1; \
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define generate_sorcery_enum_from_str_ex(__struct, __substruct, __lc_param, __unknown) \
 | 
					#define generate_sorcery_enum_to_str(__struct, __substruct, __lc_param) \
 | 
				
			||||||
 | 
						generate_sorcery_enum_to_str_ex(__struct, __substruct, __lc_param, __lc_param)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define generate_sorcery_enum_from_str_ex(__struct, __substruct, __lc_param, __base_enum, __unknown) \
 | 
				
			||||||
static int sorcery_ ## __lc_param ## _from_str(const struct aco_option *opt, struct ast_variable *var, void *obj) \
 | 
					static int sorcery_ ## __lc_param ## _from_str(const struct aco_option *opt, struct ast_variable *var, void *obj) \
 | 
				
			||||||
{ \
 | 
					{ \
 | 
				
			||||||
	struct __struct *cfg = obj; \
 | 
						struct __struct *cfg = obj; \
 | 
				
			||||||
	cfg->__substruct __lc_param = __lc_param ## _from_str (var->value); \
 | 
						cfg->__substruct __lc_param = __base_enum ## _from_str (var->value); \
 | 
				
			||||||
	if (cfg->__substruct __lc_param == __unknown) { \
 | 
						if (cfg->__substruct __lc_param == __base_enum ## _ ## __unknown) { \
 | 
				
			||||||
		ast_log(LOG_WARNING, "Unknown value '%s' specified for %s\n", \
 | 
							ast_log(LOG_WARNING, "Unknown value '%s' specified for %s\n", \
 | 
				
			||||||
			var->value, var->name); \
 | 
								var->value, var->name); \
 | 
				
			||||||
		return -1; \
 | 
							return -1; \
 | 
				
			||||||
@@ -158,7 +167,7 @@ static int sorcery_ ## __lc_param ## _from_str(const struct aco_option *opt, str
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define generate_sorcery_enum_from_str(__struct, __substruct, __lc_param, __unknown) \
 | 
					#define generate_sorcery_enum_from_str(__struct, __substruct, __lc_param, __unknown) \
 | 
				
			||||||
	generate_sorcery_enum_from_str_ex(__struct, __substruct, __lc_param, __lc_param ## _ ## __unknown) \
 | 
						generate_sorcery_enum_from_str_ex(__struct, __substruct, __lc_param, __lc_param, __unknown) \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define generate_sorcery_acl_to_str(__struct, __lc_param) \
 | 
					#define generate_sorcery_acl_to_str(__struct, __lc_param) \
 | 
				
			||||||
@@ -263,14 +272,18 @@ struct ast_acl_list *get_default_acl_list(void);
 | 
				
			|||||||
 * Copy an enum from the source to the dest only if the source is
 | 
					 * Copy an enum from the source to the dest only if the source is
 | 
				
			||||||
 * neither NOT_SET nor UNKNOWN
 | 
					 * neither NOT_SET nor UNKNOWN
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define cfg_enum_copy(__cfg_dst, __cfg_src, __field) \
 | 
					#define cfg_enum_copy_ex(__cfg_dst, __cfg_src, __field, __not_set, __unknown) \
 | 
				
			||||||
({ \
 | 
					({ \
 | 
				
			||||||
	if (__cfg_src->__field != __field ## _NOT_SET \
 | 
						if (__cfg_src->__field != __not_set \
 | 
				
			||||||
		&& __cfg_src->__field != __field ## _UNKNOWN) { \
 | 
							&& __cfg_src->__field != __unknown) { \
 | 
				
			||||||
		__cfg_dst->__field = __cfg_src->__field; \
 | 
							__cfg_dst->__field = __cfg_src->__field; \
 | 
				
			||||||
	} \
 | 
						} \
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define cfg_enum_copy(__cfg_dst, __cfg_src, __field) \
 | 
				
			||||||
 | 
						cfg_enum_copy_ex(__cfg_dst, __cfg_src, __field, __field ## _NOT_SET, __field ## _UNKNOWN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*!
 | 
					/*!
 | 
				
			||||||
 * \brief Attestation Service configuration for stir/shaken
 | 
					 * \brief Attestation Service configuration for stir/shaken
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -314,6 +327,7 @@ struct attestation_cfg {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	AST_DECLARE_STRING_FIELDS();
 | 
						AST_DECLARE_STRING_FIELDS();
 | 
				
			||||||
	struct attestation_cfg_common acfg_common;
 | 
						struct attestation_cfg_common acfg_common;
 | 
				
			||||||
 | 
						enum attest_level_enum unknown_tn_attest_level;
 | 
				
			||||||
	int global_disable;
 | 
						int global_disable;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -412,6 +426,7 @@ struct profile_cfg {
 | 
				
			|||||||
	struct attestation_cfg_common acfg_common;
 | 
						struct attestation_cfg_common acfg_common;
 | 
				
			||||||
	struct verification_cfg_common vcfg_common;
 | 
						struct verification_cfg_common vcfg_common;
 | 
				
			||||||
	enum endpoint_behavior_enum endpoint_behavior;
 | 
						enum endpoint_behavior_enum endpoint_behavior;
 | 
				
			||||||
 | 
						enum attest_level_enum unknown_tn_attest_level;
 | 
				
			||||||
	struct profile_cfg *eprofile;
 | 
						struct profile_cfg *eprofile;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -486,13 +501,13 @@ int tn_config_unload(void);
 | 
				
			|||||||
		__stringify(DEFAULT_ ## name), OPT_UINT_T, 0, \
 | 
							__stringify(DEFAULT_ ## name), OPT_UINT_T, 0, \
 | 
				
			||||||
		FLDSET(struct object, field))
 | 
							FLDSET(struct object, field))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define enum_option_register_ex(sorcery, CONFIG_TYPE, name, field, nodoc) \
 | 
					#define enum_option_register_ex(sorcery, CONFIG_TYPE, name, field, function_prefix, nodoc) \
 | 
				
			||||||
	ast_sorcery_object_field_register_custom ## nodoc(sorcery, CONFIG_TYPE, \
 | 
						ast_sorcery_object_field_register_custom ## nodoc(sorcery, CONFIG_TYPE, \
 | 
				
			||||||
		#name, field ## _to_str(DEFAULT_ ## field), \
 | 
							#name, function_prefix ## _to_str(DEFAULT_ ## field), \
 | 
				
			||||||
		sorcery_ ## field ## _from_str, sorcery_ ## field ## _to_str, NULL, 0, 0)
 | 
							sorcery_ ## field ## _from_str, sorcery_ ## field ## _to_str, NULL, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define enum_option_register(sorcery, CONFIG_TYPE, name, nodoc) \
 | 
					#define enum_option_register(sorcery, CONFIG_TYPE, name, nodoc) \
 | 
				
			||||||
	enum_option_register_ex(sorcery, CONFIG_TYPE, name, name, nodoc)
 | 
						enum_option_register_ex(sorcery, CONFIG_TYPE, name, name, name, nodoc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define register_common_verification_fields(sorcery, object, CONFIG_TYPE, nodoc) \
 | 
					#define register_common_verification_fields(sorcery, object, CONFIG_TYPE, nodoc) \
 | 
				
			||||||
({ \
 | 
					({ \
 | 
				
			||||||
@@ -510,7 +525,7 @@ int tn_config_unload(void);
 | 
				
			|||||||
	uint_option_register(sorcery, CONFIG_TYPE, object, max_cache_entry_age, vcfg_common.max_cache_entry_age, nodoc);\
 | 
						uint_option_register(sorcery, CONFIG_TYPE, object, max_cache_entry_age, vcfg_common.max_cache_entry_age, nodoc);\
 | 
				
			||||||
	uint_option_register(sorcery, CONFIG_TYPE, object, max_cache_size, vcfg_common.max_cache_size, nodoc);\
 | 
						uint_option_register(sorcery, CONFIG_TYPE, object, max_cache_size, vcfg_common.max_cache_size, nodoc);\
 | 
				
			||||||
\
 | 
					\
 | 
				
			||||||
	enum_option_register_ex(sorcery, CONFIG_TYPE, failure_action, stir_shaken_failure_action, nodoc); \
 | 
						enum_option_register_ex(sorcery, CONFIG_TYPE, failure_action, stir_shaken_failure_action, stir_shaken_failure_action, nodoc); \
 | 
				
			||||||
	enum_option_register(sorcery, CONFIG_TYPE, use_rfc9410_responses, nodoc); \
 | 
						enum_option_register(sorcery, CONFIG_TYPE, use_rfc9410_responses, nodoc); \
 | 
				
			||||||
	enum_option_register(sorcery, CONFIG_TYPE, \
 | 
						enum_option_register(sorcery, CONFIG_TYPE, \
 | 
				
			||||||
		relax_x5u_port_scheme_restrictions, nodoc); \
 | 
							relax_x5u_port_scheme_restrictions, nodoc); \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -498,11 +498,13 @@ static int pem_file_cb(const char *dir_name, const char *filename, void *obj)
 | 
				
			|||||||
	if (lstat(filename_merged, &statbuf)) {
 | 
						if (lstat(filename_merged, &statbuf)) {
 | 
				
			||||||
		printf("Error reading path stats - %s: %s\n",
 | 
							printf("Error reading path stats - %s: %s\n",
 | 
				
			||||||
					filename_merged, strerror(errno));
 | 
										filename_merged, strerror(errno));
 | 
				
			||||||
 | 
							ast_free(filename_merged);
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We only want the symlinks from the directory */
 | 
						/* We only want the symlinks from the directory */
 | 
				
			||||||
	if (!S_ISLNK(statbuf.st_mode)) {
 | 
						if (!S_ISLNK(statbuf.st_mode)) {
 | 
				
			||||||
 | 
							ast_free(filename_merged);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -512,6 +514,7 @@ static int pem_file_cb(const char *dir_name, const char *filename, void *obj)
 | 
				
			|||||||
		rc = crypto_load_store_from_cert_file(data->store, filename_merged);
 | 
							rc = crypto_load_store_from_cert_file(data->store, filename_merged);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ast_free(filename_merged);
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,7 @@
 | 
				
			|||||||
#define DEFAULT_private_key_file NULL
 | 
					#define DEFAULT_private_key_file NULL
 | 
				
			||||||
#define DEFAULT_public_cert_url NULL
 | 
					#define DEFAULT_public_cert_url NULL
 | 
				
			||||||
#define DEFAULT_attest_level attest_level_NOT_SET
 | 
					#define DEFAULT_attest_level attest_level_NOT_SET
 | 
				
			||||||
 | 
					#define DEFAULT_unknown_tn_attest_level attest_level_NOT_SET
 | 
				
			||||||
#define DEFAULT_send_mky send_mky_NOT_SET
 | 
					#define DEFAULT_send_mky send_mky_NOT_SET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void profile_destructor(void *obj)
 | 
					static void profile_destructor(void *obj)
 | 
				
			||||||
@@ -167,6 +168,9 @@ static struct profile_cfg *create_effective_profile(
 | 
				
			|||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cfg_enum_copy_ex(eprofile, acfg, unknown_tn_attest_level,
 | 
				
			||||||
 | 
							attest_level_NOT_SET, attest_level_UNKNOWN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = as_copy_cfg_common(id, &eprofile->acfg_common,
 | 
						rc = as_copy_cfg_common(id, &eprofile->acfg_common,
 | 
				
			||||||
		&base_profile->acfg_common);
 | 
							&base_profile->acfg_common);
 | 
				
			||||||
	if (rc != 0) {
 | 
						if (rc != 0) {
 | 
				
			||||||
@@ -174,6 +178,10 @@ static struct profile_cfg *create_effective_profile(
 | 
				
			|||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cfg_enum_copy_ex(eprofile, base_profile, unknown_tn_attest_level,
 | 
				
			||||||
 | 
							attest_level_NOT_SET, attest_level_UNKNOWN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eprofile->endpoint_behavior = base_profile->endpoint_behavior;
 | 
						eprofile->endpoint_behavior = base_profile->endpoint_behavior;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (eprofile->endpoint_behavior == endpoint_behavior_ON) {
 | 
						if (eprofile->endpoint_behavior == endpoint_behavior_ON) {
 | 
				
			||||||
@@ -252,6 +260,9 @@ generate_vcfg_common_sorcery_handlers(profile_cfg);
 | 
				
			|||||||
generate_sorcery_enum_from_str(profile_cfg, , endpoint_behavior, UNKNOWN);
 | 
					generate_sorcery_enum_from_str(profile_cfg, , endpoint_behavior, UNKNOWN);
 | 
				
			||||||
generate_sorcery_enum_to_str(profile_cfg, , endpoint_behavior);
 | 
					generate_sorcery_enum_to_str(profile_cfg, , endpoint_behavior);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					generate_sorcery_enum_from_str_ex(profile_cfg,,unknown_tn_attest_level, attest_level, UNKNOWN);
 | 
				
			||||||
 | 
					generate_sorcery_enum_to_str_ex(profile_cfg,,unknown_tn_attest_level, attest_level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char *cli_profile_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 | 
					static char *cli_profile_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct profile_cfg *profile;
 | 
						struct profile_cfg *profile;
 | 
				
			||||||
@@ -445,6 +456,9 @@ int profile_load(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	ast_sorcery_object_field_register_nodoc(sorcery, "eprofile", "type", "", OPT_NOOP_T, 0, 0);
 | 
						ast_sorcery_object_field_register_nodoc(sorcery, "eprofile", "type", "", OPT_NOOP_T, 0, 0);
 | 
				
			||||||
	enum_option_register(sorcery, "eprofile", endpoint_behavior, _nodoc);
 | 
						enum_option_register(sorcery, "eprofile", endpoint_behavior, _nodoc);
 | 
				
			||||||
 | 
						enum_option_register_ex(sorcery, "eprofile", unknown_tn_attest_level,
 | 
				
			||||||
 | 
							unknown_tn_attest_level, attest_level,_nodoc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	register_common_verification_fields(sorcery, profile_cfg, "eprofile", _nodoc);
 | 
						register_common_verification_fields(sorcery, profile_cfg, "eprofile", _nodoc);
 | 
				
			||||||
	register_common_attestation_fields(sorcery, profile_cfg, "eprofile", _nodoc);
 | 
						register_common_attestation_fields(sorcery, profile_cfg, "eprofile", _nodoc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -460,6 +474,9 @@ int profile_load(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	ast_sorcery_object_field_register(sorcery, CONFIG_TYPE, "type", "", OPT_NOOP_T, 0, 0);
 | 
						ast_sorcery_object_field_register(sorcery, CONFIG_TYPE, "type", "", OPT_NOOP_T, 0, 0);
 | 
				
			||||||
	enum_option_register(sorcery, CONFIG_TYPE, endpoint_behavior,);
 | 
						enum_option_register(sorcery, CONFIG_TYPE, endpoint_behavior,);
 | 
				
			||||||
 | 
						enum_option_register_ex(sorcery, CONFIG_TYPE, unknown_tn_attest_level,
 | 
				
			||||||
 | 
							unknown_tn_attest_level, attest_level,);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	register_common_verification_fields(sorcery, profile_cfg, CONFIG_TYPE,);
 | 
						register_common_verification_fields(sorcery, profile_cfg, CONFIG_TYPE,);
 | 
				
			||||||
	register_common_attestation_fields(sorcery, profile_cfg, CONFIG_TYPE,);
 | 
						register_common_attestation_fields(sorcery, profile_cfg, CONFIG_TYPE,);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,18 @@
 | 
				
			|||||||
				<configOption name="attest_level">
 | 
									<configOption name="attest_level">
 | 
				
			||||||
					<synopsis>Attestation level</synopsis>
 | 
										<synopsis>Attestation level</synopsis>
 | 
				
			||||||
				</configOption>
 | 
									</configOption>
 | 
				
			||||||
 | 
									<configOption name="unknown_tn_attest_level">
 | 
				
			||||||
 | 
										<synopsis>Attestation level to use for unknown TNs</synopsis>
 | 
				
			||||||
 | 
										<description><para>
 | 
				
			||||||
 | 
										Normally if a callerid TN isn't configured in stir_shaken.conf
 | 
				
			||||||
 | 
										no Identity header will be created. If this option is set,
 | 
				
			||||||
 | 
										however, an Identity header will be sent using this
 | 
				
			||||||
 | 
										attestation level.  Since there's no TN object, you must
 | 
				
			||||||
 | 
										ensure that a private_key_file and public_cert_url are
 | 
				
			||||||
 | 
										configured in the attestation or profile objects for
 | 
				
			||||||
 | 
										this to work.
 | 
				
			||||||
 | 
										</para></description>
 | 
				
			||||||
 | 
									</configOption>
 | 
				
			||||||
				<configOption name="check_tn_cert_public_url" default="false">
 | 
									<configOption name="check_tn_cert_public_url" default="false">
 | 
				
			||||||
					<synopsis>On load, Retrieve all TN's certificates and validate their dates</synopsis>
 | 
										<synopsis>On load, Retrieve all TN's certificates and validate their dates</synopsis>
 | 
				
			||||||
				</configOption>
 | 
									</configOption>
 | 
				
			||||||
@@ -228,6 +240,7 @@
 | 
				
			|||||||
				<xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='attestation']/configOption[@name='private_key_file'])" />
 | 
									<xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='attestation']/configOption[@name='private_key_file'])" />
 | 
				
			||||||
				<xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='attestation']/configOption[@name='public_cert_url'])" />
 | 
									<xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='attestation']/configOption[@name='public_cert_url'])" />
 | 
				
			||||||
				<xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='attestation']/configOption[@name='attest_level'])" />
 | 
									<xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='attestation']/configOption[@name='attest_level'])" />
 | 
				
			||||||
 | 
									<xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='attestation']/configOption[@name='unknown_tn_attest_level'])" />
 | 
				
			||||||
				<xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='attestation']/configOption[@name='send_mky'])" />
 | 
									<xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='attestation']/configOption[@name='send_mky'])" />
 | 
				
			||||||
				<configOption name="endpoint_behavior" default="off">
 | 
									<configOption name="endpoint_behavior" default="off">
 | 
				
			||||||
					<synopsis>Actions performed when an endpoint references this profile</synopsis>
 | 
										<synopsis>Actions performed when an endpoint references this profile</synopsis>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,8 @@
 | 
				
			|||||||
 * at the top of the source tree.
 | 
					 * at the top of the source tree.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define _TRACE_PREFIX_ "tc",__LINE__, ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "asterisk.h"
 | 
					#include "asterisk.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <sys/stat.h>
 | 
				
			||||||
@@ -108,31 +110,46 @@ static void *etn_alloc(const char *name)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct tn_cfg *tn_get_etn(const char *id, struct profile_cfg *eprofile)
 | 
					struct tn_cfg *tn_get_etn(const char *id, struct profile_cfg *eprofile)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						const char *profile_id = eprofile ? ast_sorcery_object_get_id(eprofile) : "unknown";
 | 
				
			||||||
	RAII_VAR(struct tn_cfg *, tn,
 | 
						RAII_VAR(struct tn_cfg *, tn,
 | 
				
			||||||
		ast_sorcery_retrieve_by_id(get_sorcery(), CONFIG_TYPE, S_OR(id, "")),
 | 
							ast_sorcery_retrieve_by_id(get_sorcery(), CONFIG_TYPE, S_OR(id, "")),
 | 
				
			||||||
		ao2_cleanup);
 | 
							ao2_cleanup);
 | 
				
			||||||
	struct tn_cfg *etn = etn_alloc(id);
 | 
						RAII_VAR(struct tn_cfg *, etn, etn_alloc(id), ao2_cleanup);
 | 
				
			||||||
 | 
						enum attest_level_enum effective_al = attest_level_NOT_SET;
 | 
				
			||||||
	int rc = 0;
 | 
						int rc = 0;
 | 
				
			||||||
 | 
						SCOPE_ENTER(3, "%s:%s: Getting effective TN\n", profile_id, S_OR(id, ""));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!tn || !eprofile || !etn) {
 | 
						if (ast_strlen_zero(id) || !eprofile || !etn) {
 | 
				
			||||||
		ao2_cleanup(etn);
 | 
							SCOPE_EXIT_RTN_VALUE(NULL, "Missing params\n");
 | 
				
			||||||
		return NULL;
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!tn) {
 | 
				
			||||||
 | 
							if (eprofile->unknown_tn_attest_level != attest_level_NOT_SET
 | 
				
			||||||
 | 
								&& eprofile->unknown_tn_attest_level != attest_level_UNKNOWN) {
 | 
				
			||||||
 | 
								effective_al = eprofile->unknown_tn_attest_level;
 | 
				
			||||||
 | 
								ast_trace(-1, "%s:%s: TN not found. Using unknown_tn_attest_level %s\n",
 | 
				
			||||||
 | 
									profile_id, id, attest_level_to_str(effective_al));
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								SCOPE_EXIT_RTN_VALUE(NULL, "%s:%s: TN not found and unknown_tn_attest_level not set\n", profile_id, id);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Initialize with the acfg from the eprofile first */
 | 
						/* Initialize with the acfg from the eprofile first */
 | 
				
			||||||
	rc = as_copy_cfg_common(id, &etn->acfg_common,
 | 
						rc = as_copy_cfg_common(id, &etn->acfg_common,
 | 
				
			||||||
		&eprofile->acfg_common);
 | 
							&eprofile->acfg_common);
 | 
				
			||||||
	if (rc != 0) {
 | 
						if (rc != 0) {
 | 
				
			||||||
		ao2_cleanup(etn);
 | 
							SCOPE_EXIT_RTN_VALUE(NULL, "%s:%s: Couldn't copy from eprofile\n", profile_id, id);
 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Overwrite with anything in the TN itself */
 | 
						/* Overwrite with anything in the TN itself */
 | 
				
			||||||
	rc = as_copy_cfg_common(id, &etn->acfg_common,
 | 
						if (tn) {
 | 
				
			||||||
		&tn->acfg_common);
 | 
							rc = as_copy_cfg_common(id, &etn->acfg_common,
 | 
				
			||||||
	if (rc != 0) {
 | 
								&tn->acfg_common);
 | 
				
			||||||
		ao2_cleanup(etn);
 | 
							if (rc != 0) {
 | 
				
			||||||
		return NULL;
 | 
								SCOPE_EXIT_RTN_VALUE(NULL, "%s:%s: Couldn't copy from tn\n", profile_id, id);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							etn->acfg_common.attest_level = effective_al;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
@@ -141,7 +158,7 @@ struct tn_cfg *tn_get_etn(const char *id, struct profile_cfg *eprofile)
 | 
				
			|||||||
	 * the same TN could be used with multiple profiles.
 | 
						 * the same TN could be used with multiple profiles.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return etn;
 | 
						SCOPE_EXIT_RTN_VALUE(ao2_bump(etn), "%s:%s: Done\n", profile_id, id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int tn_apply(const struct ast_sorcery *sorcery, void *obj)
 | 
					static int tn_apply(const struct ast_sorcery *sorcery, void *obj)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,9 +16,12 @@
 | 
				
			|||||||
 * at the top of the source tree.
 | 
					 * at the top of the source tree.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define _TRACE_PREFIX_ "vc",__LINE__, ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "asterisk.h"
 | 
					#include "asterisk.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "asterisk/cli.h"
 | 
					#include "asterisk/cli.h"
 | 
				
			||||||
 | 
					#include "asterisk/logger.h"
 | 
				
			||||||
#include "stir_shaken.h"
 | 
					#include "stir_shaken.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONFIG_TYPE "verification"
 | 
					#define CONFIG_TYPE "verification"
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user