如何确定openssl.cnf的默认位置?
背景
我正在编写一个bash脚本,它将使用openssl生成符合X509v3扩展标准的主题替代名称的证书签名请求。
由于没有命令行选项,因此解决方案是将-config
选项与-reqexts
选项一起使用, -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]nsubjectAltName=DNS:example.com,DNS:www.example.com")) -out domain.csr
题
我的问题是可移植性。 虽然类似的问题可以保证我的Ubuntu环境能够正常工作,因为默认的配置文件是/etc/ssl/openssl.cnf
,但不幸的是这种方式无法在任何地方使用,而Windows就是一个明显的例子。
如何以编程方式确定openssl 默认配置文件的完整路径?
我试过的
文件中有一个明显的提示
-config文件名
这允许指定备用配置文件,这将覆盖编译时间文件名或OPENSSL_CONF环境变量中指定的任何配置文件。
我读过配置文档并搜索了源代码,但是我无法发现它从何处加载“编译时”默认配置文件的机制。 如果我能找到,那么我宁愿将它作为变量加载到脚本中,而不是硬编码路径。
而且,我的$OPENSSL_CONF
变量是空的。
一个糟糕的选择
目前我的脚本检查这些条件,并使用第一个评估为真的:
$OPENSSL_CONF
变量被填充,并且文件存在 /etc/ssl/openssl.cnf
存在 如果这两个都不是真的,那么它包含一个标准配置的副本。 这是不受欢迎的,因为它实际上会覆盖由客户端建立的自定义设置。 我想完全使用环境条件,并简单地将SAN部分添加为附录。
我可以用通常的嫌疑人的路径甚至系统搜索来进一步扩展这个链条。 但是,如果存在多个,那么我不能确定openssl事实上使用哪一个作为默认值。
如何以编程方式确定openssl默认配置文件的完整路径?
编程,它一样容易使用OPENSSLDIR
从宏观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"
如何确定openssl.cnf的默认位置?
这里有更多的信息来帮助填补另一个堆栈溢出问题的空白。 这取决于您使用的OpenSSL安装。
下面是简短的回答...图书馆和程序在OPENSSLDIR
查找openssl.cnf
。 OPENSSLDIR
是一个配置选项,其设置为--openssldir
。
我在一台带有3种不同OpenSSL(苹果,MacPort和我制造的)的MacBook上:
# 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"
这是更长的答案......它被埋在OpenSSL apps.c
, load_config
源代码中,当cnf
为NULL
(即no -config
选项或OPENSSL_CONF
envar)时会发生什么。 当cnf
为NULL
且不覆盖时,则使用OPENSSLDIR
。
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 OpenSSLn");
ERR_print_errors(err);
return 0;
}
return 1;
}
...这在我的Ubuntu环境中工作,因为默认的配置文件是/etc/ssl/openssl.cnf
,不幸的是这不会在任何地方工作,Windows是一个明显的例子。
这在Windows上可能仍然是一个问题。 如果您自己从源创建OpenSSL,则应该可以; 以它们在Windows中的长文件名处理为模(也参见问题#4490:“nmake install”失败“目标必须是。 util copy.pl第39行”处的目录)。
像Shinning Light和Win32 OpenSSL这样的人提供安装程序,并且OpenSSL可能不会安装在打包程序设想的目录中。 我甚至在Windows机器上看到了像/usr/local
这样的Unix目录。
对于Windows,您最安全的选择可能是设置OPENSSL_CONF
环境变量来覆盖损坏的路径和路径处理错误。
另外,我不知道CONF_*
或NCONF_*
API调用,它会在运行时为您提供有效的目录。 在这里,有效的目录将是配置目录加上OPENSSL_CONF
覆盖之类的东西。 现在在OpenSSL用户列表中打开:在运行时获得有效的OPENSSLDIR路径?
上一篇: How to determine the default location for openssl.cnf?
下一篇: Is it important to use Characteristics.UNORDERED in Collectors when possible?