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
pull/796/head
George Joseph 1 year ago
parent 29106567e7
commit 7bbc7b5a3a

@ -351,7 +351,7 @@ struct verification_cfg_common {
enum load_system_certs_enum load_system_certs; enum load_system_certs_enum load_system_certs;
struct ast_acl_list *acl; struct ast_acl_list *acl;
X509_STORE *tcs; struct crypto_cert_store *tcs;
}; };
#define generate_vcfg_common_sorcery_handlers(object) \ #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, int crypto_get_raw_pubkey_from_cert(X509 *cert,
unsigned char **buffer) unsigned char **buffer)
{ {
RAII_VAR(BIO *, bio, NULL, BIO_free_all); RAII_VAR(EVP_PKEY *, public_key, X509_get_pubkey(cert), EVP_PKEY_free);
EVP_PKEY *public_key;
public_key = X509_get0_pubkey(cert);
if (!public_key) { if (!public_key) {
crypto_log_openssl(LOG_ERROR, "Unable to retrieve pubkey from cert\n"); crypto_log_openssl(LOG_ERROR, "Unable to retrieve pubkey from cert\n");
return -1; return -1;
@ -305,45 +303,34 @@ int crypto_extract_raw_privkey(EVP_PKEY *key, unsigned char **buffer)
return dump_mem_bio(bio, 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) { struct crypto_cert_store *store = obj;
return;
}
X509_STORE_free(store);
}
int crypto_lock_cert_store(X509_STORE *store) if (store->store) {
{ X509_STORE_free(store->store);
if (!store) {
return -1;
} }
/* lock returns 1 on success */
return X509_STORE_lock(store) == 1 ? 0 : -1;
} }
int crypto_unlock_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) { if (!store) {
return -1; ast_log(LOG_ERROR, "Failed to create crypto_cert_store\n");
return NULL;
} }
/* unlock returns 1 on success */ store->store = X509_STORE_new();
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"); crypto_log_openssl(LOG_ERROR, "Failed to create X509_STORE\n");
ao2_ref(store, -1);
return NULL; return NULL;
} }
return store; 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) const char *path)
{ {
if (ast_strlen_zero(file) && ast_strlen_zero(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; return -1;
} }
if (!store) { if (!store || !store->store) {
ast_log(LOG_ERROR, "store is NULL"); ast_log(LOG_ERROR, "store is NULL");
return -1; 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 * so openssl ignores it otherwise it'll try to open a file or
* path named ''. * 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", 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")); S_OR(file, "N/A"), S_OR(path, "N/A"));
return -1; return -1;
@ -370,14 +357,15 @@ int crypto_load_cert_store(X509_STORE *store, const char *file,
return 0; 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; STACK_OF(X509_OBJECT) *certs = NULL;
int count = 0; int count = 0;
int i = 0; int i = 0;
char subj[1024]; char subj[1024];
certs = X509_STORE_get0_objects(store); certs = X509_STORE_get0_objects(store->store);
count = sk_X509_OBJECT_num(certs); count = sk_X509_OBJECT_num(certs);
for (i = 0; i < count ; i++) { for (i = 0; i < count ; i++) {
X509_OBJECT *o = sk_X509_OBJECT_value(certs, 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); ast_cli(fd, "%s\n", subj);
} }
return count; 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) int crypto_is_cert_time_valid(X509*cert, time_t reftime)
{ {
ASN1_STRING *notbefore; ASN1_STRING *notbefore;
@ -406,7 +399,7 @@ int crypto_is_cert_time_valid(X509*cert, time_t reftime)
X509_cmp_time(notafter, &reftime) > 0); 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; X509_STORE_CTX *verify_ctx = NULL;
int rc = 0; int rc = 0;
@ -416,7 +409,7 @@ int crypto_is_cert_trusted(X509_STORE *store, X509 *cert, const char **err_msg)
return 0; 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_cleanup(verify_ctx);
X509_STORE_CTX_free(verify_ctx); X509_STORE_CTX_free(verify_ctx);
crypto_log_openssl(LOG_ERROR, "Unable to initialize verify_ctx\n"); 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); 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 * \brief Free an X509 store
* *
* \param store X509 Store to free * \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 * \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 * \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 * \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 * \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 failure
* \retval 0 success * \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); const char *path);
/*! /*!
@ -212,7 +219,7 @@ int crypto_load_cert_store(X509_STORE *store, const char *file,
* \retval <= 0 failure * \retval <= 0 failure
* \retval 0 success * \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 * \brief Unlocks an X509 Store
@ -222,7 +229,7 @@ int crypto_lock_cert_store(X509_STORE *store);
* \retval <= 0 failure * \retval <= 0 failure
* \retval 0 success * \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 * \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 1 Cert is trusted
* \retval 0 Cert is not 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 * \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, ca_path);
cfg_sf_copy_wrapper(id, cfg_dst, cfg_src, crl_file); cfg_sf_copy_wrapper(id, cfg_dst, cfg_src, crl_file);
cfg_sf_copy_wrapper(id, cfg_dst, cfg_src, crl_path); 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; cfg_dst->tcs = cfg_src->tcs;
} }
@ -230,12 +230,12 @@ int vs_check_common_config(const char *id,
if (vcfg_common->tcs) { if (vcfg_common->tcs) {
if (ENUM_BOOL(vcfg_common->load_system_certs, load_system_certs)) { 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) if (!ast_strlen_zero(vcfg_common->crl_file)
|| !ast_strlen_zero(vcfg_common->crl_path)) { || !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);
} }
} }

Loading…
Cancel
Save