]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_stir_shaken: Fix compilation for CentOS7 (openssl 1.0.2)
authorGeorge Joseph <gjoseph@sangoma.com>
Mon, 1 Apr 2024 20:10:32 +0000 (14:10 -0600)
committerAsterisk Development Team <asteriskteam@digium.com>
Thu, 9 May 2024 13:48:09 +0000 (13:48 +0000)
* 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
(cherry picked from commit 16b264d6a9cdeb4a85d225744b905ee58e184efc)

res/res_stir_shaken/common_config.h
res/res_stir_shaken/crypto_utils.c
res/res_stir_shaken/crypto_utils.h
res/res_stir_shaken/verification_config.c

index 69e9b055493357f453b05092e05e18d70d3ed2fb..c0e56b9a913e8ae8ecfa33da53959a5d4766de02 100644 (file)
@@ -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) \
index 201564bccecd07d042b1cfa6f8580d4681e9fd3b..7c4667fbb1572472e3f6c13ca72d09f7bd37e992 100644 (file)
@@ -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;
-       }
-       X509_STORE_free(store);
-}
+       struct crypto_cert_store *store = obj;
 
-int crypto_lock_cert_store(X509_STORE *store)
-{
-       if (!store) {
-               return -1;
+       if (store->store) {
+               X509_STORE_free(store->store);
        }
-       /* 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) {
-               return -1;
+               ast_log(LOG_ERROR, "Failed to create crypto_cert_store\n");
+               return NULL;
        }
-       /* 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();
+       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");
index 70538709f7b1de9d9708ee90de722345b37947dc..1f475c6521f68ae44ade82b776569c33b0dfa966 100644 (file)
@@ -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
index 4f44995b75acf745ac3587b29e91ecb6d5d1927a..0cade6bd52b5ec5e319ac69b7dc15dd39ea9b2a6 100644 (file)
@@ -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);
                }
        }