mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-11-03 20:38:59 +00:00 
			
		
		
		
	res_stir_shaken: Fix compilation for CentOS7 (openssl 1.0.2)
* OpenSSL 1.0.2 doesn't support X509_get0_pubkey so we now use X509_get_pubkey. The difference is that X509_get_pubkey requires the caller to free the EVP_PKEY themselves so we now let RAII_VAR do that. * OpenSSL 1.0.2 doesn't support upreffing an X509_STORE so we now wrap it in an ao2 object. * OpenSSL 1.0.2 doesn't support X509_STORE_get0_objects to get all the certs from an X509_STORE and there's no easy way to polyfill it so the CLI commands that list profiles will show a "not supported" message instead of listing the certs in a store. Resolves: #676
This commit is contained in:
		@@ -351,7 +351,7 @@ struct verification_cfg_common {
 | 
			
		||||
	enum load_system_certs_enum load_system_certs;
 | 
			
		||||
 | 
			
		||||
	struct ast_acl_list *acl;
 | 
			
		||||
	X509_STORE *tcs;
 | 
			
		||||
	struct crypto_cert_store *tcs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define generate_vcfg_common_sorcery_handlers(object) \
 | 
			
		||||
 
 | 
			
		||||
@@ -279,10 +279,8 @@ int crypto_extract_raw_pubkey(EVP_PKEY *key, unsigned char **buffer)
 | 
			
		||||
int crypto_get_raw_pubkey_from_cert(X509 *cert,
 | 
			
		||||
	unsigned char **buffer)
 | 
			
		||||
{
 | 
			
		||||
	RAII_VAR(BIO *, bio, NULL, BIO_free_all);
 | 
			
		||||
	EVP_PKEY *public_key;
 | 
			
		||||
	RAII_VAR(EVP_PKEY *, public_key, X509_get_pubkey(cert), EVP_PKEY_free);
 | 
			
		||||
 | 
			
		||||
	public_key = X509_get0_pubkey(cert);
 | 
			
		||||
	if (!public_key) {
 | 
			
		||||
		crypto_log_openssl(LOG_ERROR, "Unable to retrieve pubkey from cert\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
@@ -305,45 +303,34 @@ int crypto_extract_raw_privkey(EVP_PKEY *key, unsigned char **buffer)
 | 
			
		||||
	return dump_mem_bio(bio, buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void crypto_free_cert_store(X509_STORE *store)
 | 
			
		||||
static void crypto_cert_store_destructor(void *obj)
 | 
			
		||||
{
 | 
			
		||||
	if (!store) {
 | 
			
		||||
		return;
 | 
			
		||||
	struct crypto_cert_store *store = obj;
 | 
			
		||||
 | 
			
		||||
	if (store->store) {
 | 
			
		||||
		X509_STORE_free(store->store);
 | 
			
		||||
	}
 | 
			
		||||
	X509_STORE_free(store);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int crypto_lock_cert_store(X509_STORE *store)
 | 
			
		||||
struct crypto_cert_store *crypto_create_cert_store(void)
 | 
			
		||||
{
 | 
			
		||||
	struct crypto_cert_store *store = ao2_alloc(sizeof(*store), crypto_cert_store_destructor);
 | 
			
		||||
	if (!store) {
 | 
			
		||||
		return -1;
 | 
			
		||||
		ast_log(LOG_ERROR, "Failed to create crypto_cert_store\n");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	/* lock returns 1 on success */
 | 
			
		||||
	return X509_STORE_lock(store) == 1 ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
	store->store = X509_STORE_new();
 | 
			
		||||
 | 
			
		||||
int crypto_unlock_cert_store(X509_STORE *store)
 | 
			
		||||
{
 | 
			
		||||
	if (!store) {
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	/* unlock returns 1 on success */
 | 
			
		||||
	return X509_STORE_unlock(store) == 1 ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
X509_STORE *crypto_create_cert_store(void)
 | 
			
		||||
{
 | 
			
		||||
	X509_STORE *store = X509_STORE_new();
 | 
			
		||||
 | 
			
		||||
	if (!store) {
 | 
			
		||||
	if (!store->store) {
 | 
			
		||||
		crypto_log_openssl(LOG_ERROR, "Failed to create X509_STORE\n");
 | 
			
		||||
		ao2_ref(store, -1);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return store;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int crypto_load_cert_store(X509_STORE *store, const char *file,
 | 
			
		||||
int crypto_load_cert_store(struct crypto_cert_store *store, const char *file,
 | 
			
		||||
	const char *path)
 | 
			
		||||
{
 | 
			
		||||
	if (ast_strlen_zero(file) && ast_strlen_zero(path)) {
 | 
			
		||||
@@ -351,7 +338,7 @@ int crypto_load_cert_store(X509_STORE *store, const char *file,
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!store) {
 | 
			
		||||
	if (!store || !store->store) {
 | 
			
		||||
		ast_log(LOG_ERROR, "store is NULL");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
@@ -361,7 +348,7 @@ int crypto_load_cert_store(X509_STORE *store, const char *file,
 | 
			
		||||
	 * so openssl ignores it otherwise it'll try to open a file or
 | 
			
		||||
	 * path named ''.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!X509_STORE_load_locations(store, S_OR(file, NULL), S_OR(path, NULL))) {
 | 
			
		||||
	if (!X509_STORE_load_locations(store->store, S_OR(file, NULL), S_OR(path, NULL))) {
 | 
			
		||||
		crypto_log_openssl(LOG_ERROR, "Failed to load store from file '%s' or path '%s'\n",
 | 
			
		||||
			S_OR(file, "N/A"), S_OR(path, "N/A"));
 | 
			
		||||
		return -1;
 | 
			
		||||
@@ -370,14 +357,15 @@ int crypto_load_cert_store(X509_STORE *store, const char *file,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int crypto_show_cli_store(X509_STORE *store, int fd)
 | 
			
		||||
int crypto_show_cli_store(struct crypto_cert_store *store, int fd)
 | 
			
		||||
{
 | 
			
		||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
 | 
			
		||||
	STACK_OF(X509_OBJECT) *certs = NULL;
 | 
			
		||||
	int count = 0;
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	char subj[1024];
 | 
			
		||||
 | 
			
		||||
	certs = X509_STORE_get0_objects(store);
 | 
			
		||||
	certs = X509_STORE_get0_objects(store->store);
 | 
			
		||||
	count = sk_X509_OBJECT_num(certs);
 | 
			
		||||
	for (i = 0; i < count ; i++) {
 | 
			
		||||
		X509_OBJECT *o = sk_X509_OBJECT_value(certs, i);
 | 
			
		||||
@@ -386,7 +374,12 @@ int crypto_show_cli_store(X509_STORE *store, int fd)
 | 
			
		||||
		ast_cli(fd, "%s\n", subj);
 | 
			
		||||
	}
 | 
			
		||||
	return count;
 | 
			
		||||
#else
 | 
			
		||||
	ast_cli(fd, "This command is not supported until OpenSSL 1.1.0\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int crypto_is_cert_time_valid(X509*cert, time_t reftime)
 | 
			
		||||
{
 | 
			
		||||
	ASN1_STRING *notbefore;
 | 
			
		||||
@@ -406,7 +399,7 @@ int crypto_is_cert_time_valid(X509*cert, time_t reftime)
 | 
			
		||||
		X509_cmp_time(notafter, &reftime) > 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int crypto_is_cert_trusted(X509_STORE *store, X509 *cert, const char **err_msg)
 | 
			
		||||
int crypto_is_cert_trusted(struct crypto_cert_store *store, X509 *cert, const char **err_msg)
 | 
			
		||||
{
 | 
			
		||||
	X509_STORE_CTX *verify_ctx = NULL;
 | 
			
		||||
	int rc = 0;
 | 
			
		||||
@@ -416,7 +409,7 @@ int crypto_is_cert_trusted(X509_STORE *store, X509 *cert, const char **err_msg)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (X509_STORE_CTX_init(verify_ctx, store, cert, NULL) != 1) {
 | 
			
		||||
	if (X509_STORE_CTX_init(verify_ctx, store->store, cert, NULL) != 1) {
 | 
			
		||||
		X509_STORE_CTX_cleanup(verify_ctx);
 | 
			
		||||
		X509_STORE_CTX_free(verify_ctx);
 | 
			
		||||
		crypto_log_openssl(LOG_ERROR, "Unable to initialize verify_ctx\n");
 | 
			
		||||
 
 | 
			
		||||
@@ -164,20 +164,27 @@ int crypto_extract_raw_privkey(EVP_PKEY *key, unsigned char **buffer);
 | 
			
		||||
 */
 | 
			
		||||
EVP_PKEY *crypto_load_privkey_from_file(const char *filename);
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief ao2 object wrapper for X509_STORE that provides locking and refcounting
 | 
			
		||||
 */
 | 
			
		||||
struct crypto_cert_store {
 | 
			
		||||
	X509_STORE *store;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief Free an X509 store
 | 
			
		||||
 *
 | 
			
		||||
 * \param store X509 Store to free
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
void crypto_free_cert_store(X509_STORE *store);
 | 
			
		||||
#define crypto_free_cert_store(store) ao2_cleanup(store)
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief Create an empty X509 store
 | 
			
		||||
 *
 | 
			
		||||
 * \returns X509_STORE* or NULL on error
 | 
			
		||||
 * \returns crypto_cert_store * or NULL on error
 | 
			
		||||
 */
 | 
			
		||||
X509_STORE *crypto_create_cert_store(void);
 | 
			
		||||
struct crypto_cert_store *crypto_create_cert_store(void);
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief Dump a cert store to the asterisk CLI
 | 
			
		||||
@@ -187,7 +194,7 @@ X509_STORE *crypto_create_cert_store(void);
 | 
			
		||||
 | 
			
		||||
 * \retval Count of objects printed
 | 
			
		||||
 */
 | 
			
		||||
int crypto_show_cli_store(X509_STORE *store, int fd);
 | 
			
		||||
int crypto_show_cli_store(struct crypto_cert_store *store, int fd);
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief Load an X509 Store with either certificates or CRLs
 | 
			
		||||
@@ -201,7 +208,7 @@ int crypto_show_cli_store(X509_STORE *store, int fd);
 | 
			
		||||
 * \retval <= 0 failure
 | 
			
		||||
 * \retval 0 success
 | 
			
		||||
 */
 | 
			
		||||
int crypto_load_cert_store(X509_STORE *store, const char *file,
 | 
			
		||||
int crypto_load_cert_store(struct crypto_cert_store *store, const char *file,
 | 
			
		||||
	const char *path);
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
@@ -212,7 +219,7 @@ int crypto_load_cert_store(X509_STORE *store, const char *file,
 | 
			
		||||
 * \retval <= 0 failure
 | 
			
		||||
 * \retval 0 success
 | 
			
		||||
 */
 | 
			
		||||
int crypto_lock_cert_store(X509_STORE *store);
 | 
			
		||||
#define crypto_lock_cert_store(store) ao2_lock(store)
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief Unlocks an X509 Store
 | 
			
		||||
@@ -222,7 +229,7 @@ int crypto_lock_cert_store(X509_STORE *store);
 | 
			
		||||
 * \retval <= 0 failure
 | 
			
		||||
 * \retval 0 success
 | 
			
		||||
 */
 | 
			
		||||
int crypto_unlock_cert_store(X509_STORE *store);
 | 
			
		||||
#define crypto_unlock_cert_store(store) ao2_unlock(store)
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief Check if the reftime is within the cert's valid dates
 | 
			
		||||
@@ -245,7 +252,7 @@ int crypto_is_cert_time_valid(X509 *cert, time_t reftime);
 | 
			
		||||
 * \retval 1 Cert is trusted
 | 
			
		||||
 * \retval 0 Cert is not trusted
 | 
			
		||||
 */
 | 
			
		||||
int crypto_is_cert_trusted(X509_STORE *store, X509 *cert, const char **err_msg);
 | 
			
		||||
int crypto_is_cert_trusted(struct crypto_cert_store *store, X509 *cert, const char **err_msg);
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief Return a time_t for an ASN1_TIME
 | 
			
		||||
 
 | 
			
		||||
@@ -129,7 +129,7 @@ int vs_copy_cfg_common(const char *id, struct verification_cfg_common *cfg_dst,
 | 
			
		||||
		cfg_sf_copy_wrapper(id, cfg_dst, cfg_src, ca_path);
 | 
			
		||||
		cfg_sf_copy_wrapper(id, cfg_dst, cfg_src, crl_file);
 | 
			
		||||
		cfg_sf_copy_wrapper(id, cfg_dst, cfg_src, crl_path);
 | 
			
		||||
		X509_STORE_up_ref(cfg_src->tcs);
 | 
			
		||||
		ao2_bump(cfg_src->tcs);
 | 
			
		||||
		cfg_dst->tcs = cfg_src->tcs;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -230,12 +230,12 @@ int vs_check_common_config(const char *id,
 | 
			
		||||
 | 
			
		||||
	if (vcfg_common->tcs) {
 | 
			
		||||
		if (ENUM_BOOL(vcfg_common->load_system_certs, load_system_certs)) {
 | 
			
		||||
			X509_STORE_set_default_paths(vcfg_common->tcs);
 | 
			
		||||
			X509_STORE_set_default_paths(vcfg_common->tcs->store);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!ast_strlen_zero(vcfg_common->crl_file)
 | 
			
		||||
			|| !ast_strlen_zero(vcfg_common->crl_path)) {
 | 
			
		||||
			X509_STORE_set_flags(vcfg_common->tcs, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
 | 
			
		||||
			X509_STORE_set_flags(vcfg_common->tcs->store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user