24 #include "stir_shaken.h"
26 #define CONFIG_TYPE "attestation"
28 #define DEFAULT_global_disable 0
30 #define DEFAULT_check_tn_cert_public_url check_tn_cert_public_url_NO
31 #define DEFAULT_private_key_file NULL
32 #define DEFAULT_public_cert_url NULL
33 #define DEFAULT_attest_level attest_level_NOT_SET
34 #define DEFAULT_send_mky send_mky_NO
41 CONFIG_TYPE, CONFIG_TYPE);
46 return empty_cfg ?
ao2_bump(empty_cfg) : NULL;
49 int as_is_config_loaded(
void)
52 CONFIG_TYPE, CONFIG_TYPE);
66 ao2_cleanup(acfg_common->raw_key);
69 static void attestation_destructor(
void *obj)
74 acfg_cleanup(&cfg->acfg_common);
77 static void *attestation_alloc(
const char *name)
110 if (!cfg_dst || !cfg_src) {
114 cfg_sf_copy_wrapper(
id, cfg_dst, cfg_src, private_key_file);
115 cfg_sf_copy_wrapper(
id, cfg_dst, cfg_src, public_cert_url);
117 cfg_enum_copy(cfg_dst, cfg_src, attest_level);
118 cfg_enum_copy(cfg_dst, cfg_src, check_tn_cert_public_url);
119 cfg_enum_copy(cfg_dst, cfg_src, send_mky);
121 if (cfg_src->raw_key) {
123 ao2_cleanup(cfg_dst->raw_key);
124 cfg_dst->raw_key =
ao2_bump(cfg_src->raw_key);
125 cfg_dst->raw_key_length = cfg_src->raw_key_length;
133 SCOPE_ENTER(3,
"%s: Checking common config\n",
id);
135 if (!ast_strlen_zero(acfg_common->private_key_file)
137 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR,
"%s: default_private_key_path %s is missing or not readable\n",
id,
138 acfg_common->private_key_file);
141 if (ENUM_BOOL(acfg_common->check_tn_cert_public_url,
142 check_tn_cert_public_url)
143 && !ast_strlen_zero(acfg_common->public_cert_url)) {
144 RAII_VAR(
char *, public_cert_data, NULL, ast_std_free);
146 size_t public_cert_len;
149 SCOPE_ENTER(3 ,
"%s: Checking public cert url '%s'\n",
150 id, acfg_common->public_cert_url);
153 &public_cert_len, &public_cert_data, NULL);
154 if (http_code / 100 != 2) {
155 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR,
"%s: public_cert '%s' could not be downloaded\n",
id,
156 acfg_common->public_cert_url);
159 public_cert = crypto_load_cert_from_memory(public_cert_data,
162 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR,
"%s: public_cert '%s' could not be parsed as a certificate\n",
id,
163 acfg_common->public_cert_url);
165 rc = crypto_is_cert_time_valid(public_cert, 0);
166 X509_free(public_cert);
168 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR,
"%s: public_cert '%s' is not valid yet or has expired\n",
id,
169 acfg_common->public_cert_url);
172 rc = crypto_has_private_key_from_memory(public_cert_data, public_cert_len);
174 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR,
"%s: DANGER!!! public_cert_url '%s' has a private key in the file!!!\n",
id,
175 acfg_common->public_cert_url);
177 SCOPE_EXIT(
"%s: Done\n",
id);
180 if (!ast_strlen_zero(acfg_common->private_key_file)) {
181 EVP_PKEY *private_key;
182 RAII_VAR(
unsigned char *, raw_key, NULL, ast_free);
184 private_key = crypto_load_privkey_from_file(acfg_common->private_key_file);
186 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR,
"%s: Could not extract raw private key from file '%s'\n",
id,
187 acfg_common->private_key_file);
190 acfg_common->raw_key_length = crypto_extract_raw_privkey(private_key, &raw_key);
191 EVP_PKEY_free(private_key);
192 if (acfg_common->raw_key_length == 0 || raw_key == NULL) {
193 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR,
"%s: Could not extract raw private key from file '%s'\n",
id,
194 acfg_common->private_key_file);
201 acfg_common->raw_key = ao2_alloc(acfg_common->raw_key_length, NULL);
202 if (!acfg_common->raw_key) {
203 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR,
204 "%s: Could not allocate memory for raw private key\n",
id);
206 memcpy(acfg_common->raw_key, raw_key, acfg_common->raw_key_length);
210 SCOPE_EXIT_RTN_VALUE(0,
"%s: Done\n",
id);
213 static int attestation_apply(
const struct ast_sorcery *sorcery,
void *obj)
218 if (as_check_common_config(
id, &cfg->acfg_common) != 0) {
229 .title =
"Default Attestation",
230 .object_type = config_object_type_attestation,
235 e->
command =
"stir_shaken show attestation";
237 "Usage: stir_shaken show attestation\n"
238 " Show the stir/shaken attestation settings\n";
245 return CLI_SHOWUSAGE;
249 config_object_cli_show(cfg, a, &data, 0);
256 AST_CLI_DEFINE(attestation_show,
"Show stir/shaken attestation configuration"),
259 int as_config_reload(
void)
264 if (!as_is_config_loaded()) {
265 ast_log(LOG_WARNING,
"Stir/Shaken attestation service disabled. Either there were errors in the 'attestation' object in stir_shaken.conf or it was missing altogether.\n");
268 empty_cfg = attestation_alloc(CONFIG_TYPE);
272 empty_cfg->global_disable = 1;
278 int as_config_unload(
void)
281 ARRAY_LEN(attestation_cli));
282 ao2_cleanup(empty_cfg);
287 int as_config_load(
void)
291 ast_sorcery_apply_default(sorcery, CONFIG_TYPE,
"config",
292 "stir_shaken.conf,criteria=type=" CONFIG_TYPE
",single_object=yes,explicit_name=" CONFIG_TYPE);
295 NULL, attestation_apply)) {
296 ast_log(LOG_ERROR,
"stir/shaken - failed to register '%s' sorcery object\n", CONFIG_TYPE);
304 DEFAULT_global_disable ?
"yes" :
"no",
307 register_common_attestation_fields(sorcery,
attestation_cfg, CONFIG_TYPE,);
311 if (!as_is_config_loaded()) {
312 ast_log(LOG_WARNING,
"Stir/Shaken attestation service disabled. Either there were errors in the 'attestation' object in stir_shaken.conf or it was missing altogether.\n");
315 empty_cfg = attestation_alloc(CONFIG_TYPE);
319 empty_cfg->global_disable = 1;
323 ARRAY_LEN(attestation_cli));
#define ast_sorcery_object_field_register_nodoc(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object without documentation.
Asterisk main include file. File version handling, generic pbx functions.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
void ast_sorcery_force_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects even if no changes determin...
descriptor for a cli entry.
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
Full structure for sorcery.
Type for a default handler that should do nothing.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to load persistent objects.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Type for default option handler for bools (ast_true/ast_false)
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
Asterisk file paths, configured in asterisk.conf.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Attestation Service configuration for stir/shaken.
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
long curl_download_to_memory(const char *url, size_t *returned_length, char **returned_data, struct ast_variable **headers)
Really simple document retrieval to memory.
Standard Command Line Interface.
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Sorcery Data Access Layer API.