Skip to content

Commit 7e4e08c

Browse files
committed
Introduce OpenSSL INI for selecting libctx
1 parent 307ff3b commit 7e4e08c

File tree

7 files changed

+103
-32
lines changed

7 files changed

+103
-32
lines changed

ext/openssl/openssl.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -351,12 +351,39 @@ int php_openssl_get_ssl_stream_data_index(void)
351351
return ssl_stream_data_index;
352352
}
353353

354-
/* {{{ INI Settings */
354+
static PHP_INI_MH(OnUpdateLibCtx)
355+
{
356+
#if PHP_OPENSSL_API_VERSION >= 0x30000
357+
const char *name = ZSTR_VAL(new_value);
358+
359+
if (strcmp(name, "default")) {
360+
OPENSSL_G(ctx).libctx = OPENSSL_G(ctx).default_libctx;
361+
} else if (strcmp(name, "custom")) {
362+
OPENSSL_G(ctx).libctx = OPENSSL_G(ctx).custom_libctx;
363+
} else {
364+
int err_type;
365+
if (stage == ZEND_INI_STAGE_RUNTIME) {
366+
err_type = E_WARNING;
367+
} else {
368+
err_type = E_ERROR;
369+
}
370+
371+
/* Do not output error when restoring ini options. */
372+
if (stage != ZEND_INI_STAGE_DEACTIVATE) {
373+
php_error_docref(NULL, err_type, "OpenSSL libctx \"%s\" cannot be found", name);
374+
}
375+
return FAILURE;
376+
}
377+
#endif
378+
379+
return SUCCESS;
380+
}
381+
355382
PHP_INI_BEGIN()
356383
PHP_INI_ENTRY("openssl.cafile", NULL, PHP_INI_PERDIR, NULL)
357384
PHP_INI_ENTRY("openssl.capath", NULL, PHP_INI_PERDIR, NULL)
385+
PHP_INI_ENTRY("openssl.libctx", "custom", PHP_INI_PERDIR, OnUpdateLibCtx)
358386
PHP_INI_END()
359-
/* }}} */
360387

361388
/* {{{ PHP_MINIT_FUNCTION */
362389
PHP_MINIT_FUNCTION(openssl)
@@ -438,9 +465,7 @@ PHP_GINIT_FUNCTION(openssl)
438465
#endif
439466
openssl_globals->errors = NULL;
440467
openssl_globals->errors_mark = NULL;
441-
#if PHP_OPENSSL_API_VERSION >= 0x30000
442-
php_openssl_backend_init_libctx(&openssl_globals->libctx, &openssl_globals->propq);
443-
#endif
468+
php_openssl_backend_init_libctx(&openssl_globals->ctx);
444469
}
445470
/* }}} */
446471

@@ -453,9 +478,7 @@ PHP_GSHUTDOWN_FUNCTION(openssl)
453478
if (openssl_globals->errors_mark) {
454479
pefree(openssl_globals->errors_mark, 1);
455480
}
456-
#if PHP_OPENSSL_API_VERSION >= 0x30000
457-
php_openssl_backend_destroy_libctx(openssl_globals->libctx, openssl_globals->propq);
458-
#endif
481+
php_openssl_backend_destroy_libctx(&openssl_globals->ctx);
459482
}
460483
/* }}} */
461484

ext/openssl/openssl_backend_v1.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ void php_openssl_backend_shutdown(void)
4444
#endif
4545
}
4646

47+
void php_openssl_backend_init_libctx(struct php_openssl_libctx *ctx)
48+
{
49+
// Do nothing as there is no libctx
50+
}
51+
52+
void php_openssl_backend_destroy_libctx(struct php_openssl_libctx *ctx)
53+
{
54+
// Do nothing as there is no libctx
55+
}
56+
4757
EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id)
4858
{
4959
return EVP_PKEY_CTX_new_id(id, NULL);

ext/openssl/openssl_backend_v3.c

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,32 +29,47 @@ void php_openssl_backend_shutdown(void)
2929
(void) 0;
3030
}
3131

32-
void php_openssl_backend_init_libctx(OSSL_LIB_CTX **plibctx, char **ppropq)
32+
# define PHP_OPENSSL_DEFAULT_CONF_MFLAGS \
33+
(CONF_MFLAGS_DEFAULT_SECTION | CONF_MFLAGS_IGNORE_MISSING_FILE | CONF_MFLAGS_IGNORE_RETURN_CODES)
34+
35+
void php_openssl_backend_init_libctx(struct php_openssl_libctx *ctx)
3336
{
34-
/* The return value is not checked because we cannot reasonable fail in GINIT so using NULL
35-
* (default context) is probably better. */
36-
*plibctx = OSSL_LIB_CTX_new();
37-
*ppropq = NULL;
37+
ctx->default_libctx = OSSL_LIB_CTX_get0_global_default();
38+
ctx->custom_libctx = OSSL_LIB_CTX_new();
39+
if (ctx->custom_libctx != NULL) {
40+
/* This is not being checked because there is not much that can be done. */
41+
CONF_modules_load_file_ex(ctx->custom_libctx, NULL, NULL,
42+
PHP_OPENSSL_DEFAULT_CONF_MFLAGS);
43+
#ifdef LOAD_OPENSSL_LEGACY_PROVIDER
44+
OSSL_PROVIDER_load(ctx->custom_libctx, "legacy");
45+
OSSL_PROVIDER_load(ctx->custom_libctx, "default");
46+
#endif
47+
ctx->libctx = ctx->custom_libctx;
48+
} else {
49+
/* If creation fails, just fallback to default */
50+
ctx->libctx = ctx->default_libctx;
51+
}
52+
ctx->propq = NULL;
3853
}
3954

40-
void php_openssl_backend_destroy_libctx(OSSL_LIB_CTX *libctx, char *propq)
55+
void php_openssl_backend_destroy_libctx(struct php_openssl_libctx *ctx)
4156
{
42-
if (libctx != NULL) {
43-
OSSL_LIB_CTX_free(libctx);
57+
if (ctx->custom_libctx != NULL) {
58+
OSSL_LIB_CTX_free(ctx->custom_libctx);
4459
}
45-
if (propq != NULL) {
46-
free(propq);
60+
if (ctx->propq != NULL) {
61+
free(ctx->propq);
4762
}
4863
}
4964

5065
EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id)
5166
{
52-
return EVP_PKEY_CTX_new_from_name(OPENSSL_G(libctx), name, OPENSSL_G(propq));
67+
return EVP_PKEY_CTX_new_from_name(PHP_OPENSSL_LIBCTX, name, PHP_OPENSSL_PROPQ);
5368
}
5469

5570
EVP_PKEY_CTX *php_openssl_pkey_new_from_pkey(EVP_PKEY *pkey)
5671
{
57-
return EVP_PKEY_CTX_new_from_pkey(OPENSSL_G(libctx), pkey, OPENSSL_G(propq));
72+
return EVP_PKEY_CTX_new_from_pkey(PHP_OPENSSL_LIBCTX, pkey, PHP_OPENSSL_PROPQ);
5873
}
5974

6075
EVP_PKEY *php_openssl_pkey_init_rsa(zval *data)
@@ -299,7 +314,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
299314
goto cleanup;
300315
}
301316

302-
if (!(group = EC_GROUP_new_by_curve_name_ex(OPENSSL_G(libctx), OPENSSL_G(propq), nid))) {
317+
if (!(group = EC_GROUP_new_by_curve_name_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ, nid))) {
303318
goto cleanup;
304319
}
305320

@@ -698,7 +713,7 @@ zend_string *php_openssl_dh_compute_key(EVP_PKEY *pkey, char *pub_str, size_t pu
698713

699714
const EVP_MD *php_openssl_get_evp_md_by_name(const char *name)
700715
{
701-
return EVP_MD_fetch(OPENSSL_G(libctx), name, OPENSSL_G(propq));
716+
return EVP_MD_fetch(PHP_OPENSSL_LIBCTX, name, PHP_OPENSSL_PROPQ);
702717
}
703718

704719
static const char *php_openssl_digest_names[] = {
@@ -754,7 +769,7 @@ static const char *php_openssl_cipher_names[] = {
754769

755770
const EVP_CIPHER *php_openssl_get_evp_cipher_by_name(const char *name)
756771
{
757-
return EVP_CIPHER_fetch(OPENSSL_G(libctx), name, OPENSSL_G(propq));
772+
return EVP_CIPHER_fetch(PHP_OPENSSL_LIBCTX, name, PHP_OPENSSL_PROPQ);
758773
}
759774

760775
const EVP_CIPHER *php_openssl_get_evp_cipher_from_algo(zend_long algo)
@@ -805,7 +820,7 @@ static int php_openssl_compare_func(Bucket *a, Bucket *b)
805820
void php_openssl_get_cipher_methods(zval *return_value, bool aliases)
806821
{
807822
array_init(return_value);
808-
EVP_CIPHER_do_all_provided(OPENSSL_G(libctx),
823+
EVP_CIPHER_do_all_provided(PHP_OPENSSL_LIBCTX,
809824
aliases ? php_openssl_add_cipher_or_alias : php_openssl_add_cipher,
810825
return_value);
811826
zend_hash_sort(Z_ARRVAL_P(return_value), php_openssl_compare_func, 1);

ext/openssl/php_openssl.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,24 @@ struct php_openssl_errors {
7070
int bottom;
7171
};
7272

73-
ZEND_BEGIN_MODULE_GLOBALS(openssl)
74-
struct php_openssl_errors *errors;
75-
struct php_openssl_errors *errors_mark;
73+
struct php_openssl_libctx {
7674
#if PHP_OPENSSL_API_VERSION >= 0x30000
7775
OSSL_LIB_CTX *libctx;
78-
char *propq;
76+
OSSL_LIB_CTX *default_libctx;
77+
OSSL_LIB_CTX *custom_libctx;
7978
#endif
79+
char *propq;
80+
};
81+
82+
ZEND_BEGIN_MODULE_GLOBALS(openssl)
83+
struct php_openssl_errors *errors;
84+
struct php_openssl_errors *errors_mark;
85+
struct php_openssl_libctx ctx;
8086
ZEND_END_MODULE_GLOBALS(openssl)
8187

88+
#define PHP_OPENSSL_LIBCTX OPENSSL_G(ctx).libctx
89+
#define PHP_OPENSSL_PROPQ OPENSSL_G(ctx).propq
90+
8291
#define OPENSSL_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(openssl, v)
8392

8493
#if defined(ZTS) && defined(COMPILE_DL_OPENSSL)

ext/openssl/php_openssl_backend.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,8 @@ void php_openssl_backend_init_common(void);
237237
void php_openssl_backend_gshutdown(void);
238238
void php_openssl_backend_shutdown(void);
239239

240-
#if PHP_OPENSSL_API_VERSION >= 0x30000
241-
void php_openssl_backend_init_libctx(OSSL_LIB_CTX **plibctx, char **ppropq);
242-
void php_openssl_backend_destroy_libctx(OSSL_LIB_CTX *libctx, char *propq);
243-
#endif
240+
void php_openssl_backend_init_libctx(struct php_openssl_libctx *ctx);
241+
void php_openssl_backend_destroy_libctx(struct php_openssl_libctx *ctx);
244242

245243
const char *php_openssl_get_conf_filename(void);
246244

php.ini-development

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,14 @@ ldap.max_links = -1
18571857
; SSL stream context option.
18581858
;openssl.capath=
18591859

1860+
; The libctx is an OpenSSL library context. OpenSSL defines a default library
1861+
; context, but PHP OpenSSL also defines its own library context to avoid
1862+
; interference with other libraries using OpenSSL and to provide an independent
1863+
; context for each thread in ZTS. Possible values:
1864+
; "custom" - use a custom library context (default)
1865+
; "default" - use the default OpenSSL library context
1866+
;openssl.libctx=custom
1867+
18601868
[ffi]
18611869
; FFI API restriction. Possible values:
18621870
; "preload" - enabled in CLI scripts and preloaded files (default)

php.ini-production

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,6 +1859,14 @@ ldap.max_links = -1
18591859
; SSL stream context option.
18601860
;openssl.capath=
18611861

1862+
; The libctx is an OpenSSL library context. OpenSSL defines a default library
1863+
; context, but PHP OpenSSL also defines its own library context to avoid
1864+
; interference with other libraries using OpenSSL and to provide an independent
1865+
; context for each thread in ZTS. Possible values:
1866+
; "custom" - use a custom library context (default)
1867+
; "default" - use the default OpenSSL library context
1868+
;openssl.libctx=custom
1869+
18621870
[ffi]
18631871
; FFI API restriction. Possible values:
18641872
; "preload" - enabled in CLI scripts and preloaded files (default)

0 commit comments

Comments
 (0)