check_cert() uses system CA store even if user provided own cert to be used as CA
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- C
- Star
- 40.4k
- Fork
- 8.1k
- Merge trung bình
- 2 ngày 13 giờ
- Pull request đã merge (30 ngày)
- 96
Mô tả
Description
I was trying to figure out why this code
<?php
$cert = file_get_contents("single-letsencrypt-domain-cert.pem")
print_r(openssl_x509_checkpurpose($cert, X509_PURPOSE_SSL_SERVER, array('letsencrypt-intermediate.pem')));
worked (returned True) on some systems while on other returned False. Turns out the key difference is that one system had CA certificates in a bundle ONLY:
/etc/pki/tls/certs/ca-bundle.crt
while the other system had above bundle BUT also individual hashed CA certs in /etc/openssl/certs/ directory.
/etc/pki/tls/certs/ca-bundle.crt
/etc/openssl/certs/*.0 (bunch of hashes as symlinks to actual individual CA cert files)
(note this is on PLD/Linux, so on your system layout can be different)
Now openssl_x509_checkpurpose() third parameter is "ca_info should be an array of trusted CA files/dirs as described in Certificate Verification."
I assume the goal is to override system CA certs. (My assumption is also based on how/when check_cert() tries to load system CA certs)
openssl_x509_checkpurpose() then uses check_cert() to load CA certs.
Unfortunately the code is like this
[code from php 8.5 git]
parse what user has specified in ca_info (calist), if some files then "nfiles++", if dirs then "ndirs++",
load what user specified (if possible) and then handle system CA certs but do it in such way:
832 if (nfiles == 0) {
833 file_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
834 if (file_lookup == NULL || !X509_LOOKUP_load_file(file_lookup, NULL, X509_FILETYPE_DEFAULT)) {
835 php_openssl_store_errors();
836 }
837 }
838 if (ndirs == 0) {
839 dir_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
840 if (dir_lookup == NULL || !X509_LOOKUP_add_dir(dir_lookup, NULL, X509_FILETYPE_DEFAULT)) {
841 php_openssl_store_errors();
842 }
843 }
Which means:
- if user specified (in ca_info) any files and only files then sytem CA files won't be loaded BUT sytem directories will (due to ndirs==0)!
- if user specified (in ca_info) any directories and only directories then sytem CA directories won't be loaded BUT sytem files will (due to nfiles==0)!
- if user specified (in ca_info) any files and any directories then no CA files and no CA directories will be used (due to ndirs > 0 and nfiles > 0).
That makes no sense. Partial system CA is getting kind of "randomly" loaded only based on file vs directory type.
I would expect only user provided CA files/dirs to be used and no system CA store if user uses anything valid as ca_info parameter of openssl_x509_checkpurpose()
So the fix - use system CA certs in form of files and directories only if user didn't override these with own ca_info (calist) parameter.
diff --git a/ext/openssl/openssl_backend_common.c b/ext/openssl/openssl_backend_common.c
index c21e64a1306..1f4509f40f0 100644
--- a/ext/openssl/openssl_backend_common.c
+++ b/ext/openssl/openssl_backend_common.c
@@ -829,13 +829,11 @@ X509_STORE *php_openssl_setup_verify(zval *calist, uint32_t arg_num)
}
} ZEND_HASH_FOREACH_END();
}
- if (nfiles == 0) {
+ if (nfiles == 0 && ndirs == 0) {
file_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
if (file_lookup == NULL || !X509_LOOKUP_load_file(file_lookup, NULL, X509_FILETYPE_DEFAULT)) {
php_openssl_store_errors();
}
- }
- if (ndirs == 0) {
dir_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
if (dir_lookup == NULL || !X509_LOOKUP_add_dir(dir_lookup, NULL, X509_FILETYPE_DEFAULT)) {
php_openssl_store_errors();
PHP Version
$ php84 --version
PHP 8.4.13 (cli) (built: Sep 27 2025 01:01:24) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.4.13, Copyright (c) Zend Technologies
(tests were done on this php)
Operating System
PLD/Linux current Th
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu trong ext/openssl/openssl_backend_common.c tại php_openssl_setup_verify() và đường đi check_cert(). Tái hiện ví dụ openssl_x509_checkpurpose() với các giá trị ca_info chỉ chứa tệp, chỉ chứa thư mục và kết hợp cả hai. Hoàn thành khi các tệp hoặc thư mục CA hợp lệ do người dùng cung cấp ngăn kho CA hệ thống được tải một phần.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- c, php
- Lĩnh vực
- backend, security
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 55/100