如何确定 openssl.cnf 的默认位置? [英] How to determine the default location for openssl.cnf?
问题描述
背景
我正在编写一个 bash 脚本,该脚本将使用 openssl 生成具有X509v3 扩展兼容主题替代名称的证书签名请求.
由于没有命令行选项,一个解决方案是将 -config
选项与 -reqexts
选项结合使用,通过将 SAN 值附加到默认配置文件.
openssl req -new -sha256 -key domain.key -subj "/C=US/ST=CA/O=Acme, Inc./CN=example.com" -reqexts SAN -config <(cat/etc/ssl/openssl.cnf <(printf "[SAN]
subjectAltName=DNS:example.com,DNS:www.example.com")) -out domain.csr
问题
我的问题是便携性.虽然 a similar question 向我保证这在我的 Ubuntu 环境中有效,因为默认配置文件是 /etc/ssl/openssl.cnf
,不幸的是,这不适用于任何地方,Windows 就是一个明显的例子.
我如何以编程方式确定 openssl 默认 配置文件的完整路径?
我的尝试
<块引用>-配置文件名
这允许指定备用配置文件,这会覆盖编译时文件名或在 OPENSSL_CONF 环境变量中指定的任何文件名.
我已阅读 配置文档 并搜索了源代码,但我无法发现它选择从何处加载编译时间"的机制" 默认配置文件.如果我能找到,那么我更愿意将它作为变量加载到脚本中,而不是硬编码的路径中.
此外,我的 $OPENSSL_CONF
变量是空的.
一个糟糕的选择
目前我的脚本检查这些条件,并使用第一个评估为真的条件:
$OPENSSL_CONF
变量已填充,文件存在/etc/ssl/openssl.cnf
存在
如果这些都不是真的,那么它包含一个标准配置的副本.这是不可取的,因为它实际上会覆盖客户端建立的自定义设置.我想完全利用环境的条件,简单的把SAN部分作为附录添加.
我可以使用常见嫌疑人的路径甚至系统搜索来进一步扩展此链.但是如果存在多个,那么我无法保证 openssl 实际上使用哪个作为默认值.
如何以编程方式确定 openssl 默认配置文件的完整路径?
以编程方式,就像使用 opensslconf.h
中的 OPENSSLDIR
宏一样简单:
$ cat/usr/local/ssl/darwin/include/openssl/opensslconf.h |grep OPENSSLDIR#if 定义(HEADER_CRYPTLIB_H)&&!defined(OPENSSLDIR)#define OPENSSLDIR "/usr/local/ssl/darwin"
<小时><块引用>
如何确定openssl.cnf的默认位置?
这里有更多信息可以帮助填补其他 Stack Overflow 问题中的空白.这取决于您使用的 OpenSSL 安装.
这是简短的回答...库和程序在 OPENSSLDIR
中查找 openssl.cnf
.OPENSSLDIR
是一个配置选项,它用 --openssldir
设置.
我在 MacBook 上使用 3 个不同的 OpenSSL(Apple 的、MacPort 的和我构建的):
# Apple$/usr/bin/openssl 版本 -a |grep OPENSSLDIROPENSSLDIR:/系统/库/OpenSSL"# MacPorts$/opt/local/bin/openssl 版本 -a |grep OPENSSLDIROPENSSLDIR: "/opt/local/etc/openssl"# 我的 OpenSSL 构建$ openssl 版本 -a |grep OPENSSLDIROPENSSLDIR: "/usr/local/ssl/darwin"
这是更长的答案......它有点隐藏在 apps.c
、load_config
和 cnf
的 OpenSSL 源代码中> 是 NULL
(即没有 -config
选项或 OPENSSL_CONF
envar).当 cnf
为 NULL
且没有覆盖时,则使用 OPENSSLDIR
.
int load_config(BIO *err, CONF *cnf){静态 int load_config_call = 0;如果(load_config_call)返回 1;load_config_call = 1;如果(!cnf)cnf = 配置;如果(!cnf)返回 1;OPENSSL_load_builtin_modules();如果 (CONF_modules_load(cnf, NULL, 0) <= 0) {BIO_printf(err, "错误配置 OpenSSL
");ERR_print_errors(err);返回0;}返回 1;}
<小时><块引用>
...这适用于我的 Ubuntu 环境,因为默认配置文件是 /etc/ssl/openssl.cnf
,不幸的是,这不适用于任何地方,Windows 就是一个明显的例子.
在 Windows 上这对您来说可能仍然是一个问题.如果您自己从源代码构建 OpenSSL,您应该没问题;在 Windows 中对它们的长文件名处理取模(另请参阅 Issue#4490:nmake install"失败目标必须是位于 .utilcopy.pl line 39 的目录").
Shinning Light 和 Win32 OpenSSL 等人提供安装程序,而 OpenSSL 可能不 安装在打包者预想的目录中.我什至看到像 /usr/local
这样的 Unix 目录出现在 Windows 机器上.
对于 Windows,您最安全的选择可能是设置 OPENSSL_CONF
环境变量以覆盖损坏的路径和路径处理错误.
此外,我不知道在运行时为您提供有效目录的 CONF_*
或 NCONF_*
API 调用.在这里,有效目录将是配置目录加上诸如 OPENSSL_CONF
覆盖之类的内容.现在在 OpenSSL 用户列表上打开:在运行时获取有效的 OPENSSLDIR 路径?
Background
I'm writing a bash script that will use openssl to generate a certificate signing request with X509v3 extension compliant subject alternative names.
Since there's no command line option for this, a solution has been to use the -config
option in conjunction with the -reqexts
option by appending the SAN values inline to the default configuration file.
openssl req -new -sha256 -key domain.key -subj "/C=US/ST=CA/O=Acme, Inc./CN=example.com" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]
subjectAltName=DNS:example.com,DNS:www.example.com")) -out domain.csr
Question
My problem is portability. While a similar question assures me that this works in my Ubuntu environment because the default configuration file is /etc/ssl/openssl.cnf
, unfortunately this won't work everywhere, with Windows being the obvious example.
How do I programmatically determine the full path to the openssl default configuration file?
What I've Tried
There's a glaring hint in the documentation
-config filename
this allows an alternative configuration file to be specified, this overrides the compile time filename or any specified in the OPENSSL_CONF environment variable.
I've read the config documentation and searched the source code, but I can't discover the mechanism by which it chooses from where to load the "compile time" default config file. If I could find that, then I would prefer to load it as a variable into the script instead of the hard-coded path.
Moreover, my $OPENSSL_CONF
variable is empty.
A Bad Alternative
Currently my script checks these conditions, and uses the first one that evaluates to true:
$OPENSSL_CONF
variable is populated, and file exists/etc/ssl/openssl.cnf
exists
If neither of those are true, then it includes a copy of a standard configuration. This is undesirable because it would in effect override custom settings established by the client. I want to use the environment's conditions completely, and simply add the SAN section as an addendum.
I could further extend this chain with the paths of the usual suspects or even a system search. But in the event that multiple exist, then I have no assurance of which is in fact used by openssl as a default.
How do I programmatically determine the full path to the openssl default configuration file?
Programmatically, its as easy as using the OPENSSLDIR
macro from opensslconf.h
:
$ cat /usr/local/ssl/darwin/include/openssl/opensslconf.h | grep OPENSSLDIR
#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR)
#define OPENSSLDIR "/usr/local/ssl/darwin"
How to determine the default location for openssl.cnf?
Here's more information to help fill in the gaps from the other Stack Overflow question. It depends on the OpenSSL installation you are using.
Here's the short answer... The library and programs look for openssl.cnf
in OPENSSLDIR
. OPENSSLDIR
is a configure option, and its set with --openssldir
.
I'm on a MacBook with 3 different OpenSSL's (Apple's, MacPort's and the one I build):
# Apple
$ /usr/bin/openssl version -a | grep OPENSSLDIR
OPENSSLDIR: "/System/Library/OpenSSL"
# MacPorts
$ /opt/local/bin/openssl version -a | grep OPENSSLDIR
OPENSSLDIR: "/opt/local/etc/openssl"
# My build of OpenSSL
$ openssl version -a | grep OPENSSLDIR
OPENSSLDIR: "/usr/local/ssl/darwin"
Here's the longer answer... It is kind of buried in OpenSSL source code for apps.c
, load_config
and what happens when cnf
is NULL
(i.e., no -config
option or OPENSSL_CONF
envar). When cnf
is NULL
and no overrides, then OPENSSLDIR
is used.
int load_config(BIO *err, CONF *cnf)
{
static int load_config_called = 0;
if (load_config_called)
return 1;
load_config_called = 1;
if (!cnf)
cnf = config;
if (!cnf)
return 1;
OPENSSL_load_builtin_modules();
if (CONF_modules_load(cnf, NULL, 0) <= 0) {
BIO_printf(err, "Error configuring OpenSSL
");
ERR_print_errors(err);
return 0;
}
return 1;
}
... this works in my Ubuntu environment because the default configuration file is
/etc/ssl/openssl.cnf
, unfortunately this won't work everywhere, with Windows being the obvious example.
This may still be a problem for you on Windows. You should be OK if you build OpenSSL from sources yourself; modulo their long filename handling in Windows (also see Issue #4490: "nmake install" fails "Destination must be a directory at .utilcopy.pl line 39" on).
Folks like Shinning Light and Win32 OpenSSL provide installers, and OpenSSL may not be installed in the directory the packager envisioned. I've even seen Unix directories like /usr/local
appear on Windows machines.
For Windows, your safest bet is probably set the OPENSSL_CONF
environmental variable to override broken paths and path handling bugs.
Also, I'm not aware of a CONF_*
or NCONF_*
API call that gives you the effective directory at runtime. Here, the effective directory would be the configuration directory plus things like OPENSSL_CONF
overrides. Now open on the OpenSSL User list: Get effective OPENSSLDIR path at runtime?
这篇关于如何确定 openssl.cnf 的默认位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!