當你有所疑惑時,就去閱讀 PHP 的原始碼!
`$configargs` 的底層運作方式相當不透明。除非你實際去查看 `/ext/openssl/openssl.c` 中的 `php_openssl_parse_config()` 函式。
SET_OPTIONAL_STRING_ARG("digest_alg", req->digest_name,
CONF_get_string(req->req_config, req->section_name, "default_md"));
SET_OPTIONAL_STRING_ARG("x509_extensions", req->extensions_section,
CONF_get_string(req->req_config, req->section_name, "x509_extensions"));
SET_OPTIONAL_STRING_ARG("req_extensions", req->request_extensions_section,
CONF_get_string(req->req_config, req->section_name, "req_extensions"));
SET_OPTIONAL_LONG_ARG("private_key_bits", req->priv_key_bits,
CONF_get_number(req->req_config, req->section_name, "default_bits"));
SET_OPTIONAL_LONG_ARG("private_key_type", req->priv_key_type, OPENSSL_KEYTYPE_DEFAULT);
我們可以看到,大多數輸入都呼叫了 `SET_OPTIONAL_STRING_ARG()`,但 `'private_key_bits'` 卻呼叫了 `SET_OPTIONAL_LONG_ARG()`。這兩個呼叫都是 C 巨集,它們會展開成強制執行預期輸入類型的程式碼。如果使用了非預期的類型,產生的程式碼會忽略輸入,並且不會發出任何警告或通知,只會使用設定檔中的預設值。這就是為什麼對 `'private_key_bits'` 使用字串會導致非預期行為的原因。
進一步檢視同一個函式中較早的初始化:
SET_OPTIONAL_STRING_ARG("config", req->config_filename, default_ssl_conf_filename);
SET_OPTIONAL_STRING_ARG("config_section_name", req->section_name, "req");
req->global_config = CONF_load(NULL, default_ssl_conf_filename, NULL);
req->req_config = CONF_load(NULL, req->config_filename, NULL);
if (req->req_config == NULL) {
return FAILURE;
}
以及在另一個函式中的其他地方:
/* 如果沒有設定環境變數,則預設為 'openssl.cnf' */
if (config_filename == NULL) {
snprintf(default_ssl_conf_filename, sizeof(default_ssl_conf_filename), "%s/%s",
X509_get_default_cert_area(),
"openssl.cnf");
} else {
strlcpy(default_ssl_conf_filename, config_filename, sizeof(default_ssl_conf_filename));
}
揭示了 `$configargs` 中的 `config` 會覆蓋其他地方的任何預設設定。這實際上否定了文件中「注意:您需要安裝有效的 openssl.cnf 才能使此函數正常運作。有關更多資訊,請參閱安裝章節下的注意事項。」這段註釋。更正確的句子應該是「注意:您需要設定有效的 openssl.cnf 或使用 `$configargs` 指向有效的 openssl.cnf 檔案,才能使此函數正常運作。」
所有這些都表明,查看 PHP 原始碼是了解實際情況的唯一真正方法。這樣做可以節省時間和精力。