我正在编写一个bash脚本,该脚本将使用openssl生成符合 X509v3扩展名主题备用名称的证书签名请求。
由于没有这样的命令行选项,a solution已将-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]\nsubjectAltName=DNS:example.com,DNS:www.example.com")) -out domain.csr
我的问题是便携性。虽然a similar question向我保证这可以在我的Ubuntu环境中运行,因为默认配置文件是/etc/ssl/openssl.cnf
,但不幸的是,这无处不在,Windows就是明显的例子。
如何以编程方式确定openssl 默认配置文件的完整路径?
-config filename
这允许指定备用配置文件,这将覆盖编译时文件名或OPENSSL_CONF环境变量中指定的任何文件。
我已经阅读了config documentation并搜索了source code,但我无法找到从哪里加载&#34;编译时间&#的机制34;默认配置文件。如果我能找到,那么我宁愿将其作为变量加载到脚本而不是硬编码路径中。
此外,我的$OPENSSL_CONF
变量为空。
目前我的脚本检查这些条件,并使用第一个评估为true的条件:
$OPENSSL_CONF
变量已填充,文件存在/etc/ssl/openssl.cnf
存在如果这些都不是真的,那么它包括标准配置的副本。这是不合需要的,因为它实际上会覆盖客户端建立的自定义设置。我想完全使用环境条件,只需添加SAN部分作为附录。
我可以用通常的嫌疑人甚至系统搜索的路径进一步扩展这个链。但是如果存在多个,那么我无法保证openssl实际上将其用作默认值。
答案 0 :(得分:8)
如何以编程方式确定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的默认位置?
这里有更多信息可以帮助填补其他Stack Overflow问题的空白。这取决于您使用的OpenSSL安装。
这是简短的答案......图书馆和程序会在openssl.cnf
中查找OPENSSLDIR
。 OPENSSLDIR
是一个配置选项,其设置为--openssldir
。
我在MacBook上有3种不同的OpenSSL(Apple,MacPort和我建的):
# 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"
这是更长的答案......它隐藏在apps.c
,load_config
的OpenSSL源代码中,以及当cnf
为NULL
时会发生什么(即没有-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 OpenSSL\n");
ERR_print_errors(err);
return 0;
}
return 1;
}
...这在我的Ubuntu环境中有效,因为默认配置文件是
/etc/ssl/openssl.cnf
,遗憾的是这在任何地方都不起作用,Windows就是一个明显的例子。
在Windows上,这可能仍然是一个问题。如果您自己从源代码构建OpenSSL,那么您应该没问题;在Windows中模拟它们的长文件名处理(另见Issue #4490: "nmake install" fails "Destination must be a directory at .\util\copy.pl line 39" on)。
像Shinning Light and Win32 OpenSSL这样的人提供安装程序,并且OpenSSL 可能不会安装在打包程序所设想的目录中。我甚至看到像/usr/local
这样的Unix目录出现在Windows机器上。
对于Windows,您最安全的选择可能是设置OPENSSL_CONF
环境变量来覆盖损坏的路径和路径处理错误。
另外,我不知道CONF_*
或NCONF_*
API调用会在运行时为您提供有效的目录。这里,有效目录将是配置目录以及OPENSSL_CONF
覆盖之类的内容。现在在OpenSSL用户列表中打开:Get effective OPENSSLDIR path at runtime?
答案 1 :(得分:4)
如评论之一所述,简单的答案应该是使用以下命令找到路径:
openssl version -d
如果这不起作用,则可以假定未正确配置OpenSSL,或者至少没有所需的配置。这是Node.js中有关如何获取openssl.cnf位置的示例:
const util = require('util');
const path = require('path');
const exec = util.promisify(require('child_process').exec);
(async () => {
const opensslCnfPath = path.normalize(`${(await exec('openssl version -d')).stdout.match(/"(.*)"/).pop()}/openssl.cnf`);
console.log(opensslCnfPath);
})();