我正在编写一个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默认配置文件的完整路径?
我试过的
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.
我已经阅读了config documentation并搜索了source code,但是我无法找到它从何处加载“编译时”默认配置文件的机制.如果我能找到它,那么我宁愿将其作为变量加载到脚本而不是硬编码路径中.
而且,我的$OPENSSL_CONF变量是空的.
不良选择
目前我的脚本检查这些条件,并使用第一个评估为true的条件:
> $OPENSSL_CONF变量已填充,文件存在
> /etc/ssl/openssl.cnf存在
如果这些都不是真的,那么它包括标准配置的副本.这是不合需要的,因为它实际上会覆盖客户端建立的自定义设置.我想完全使用环境条件,只需添加SAN部分作为附录.
我可以用通常的嫌疑人的路径甚至系统搜索进一步扩展这个链.但是如果存在多个,那么我无法保证openssl实际上将其用作默认值.
How do I programmatically determine the full path to the openssl default configuration file?
以编程方式,它就像使用opensslconf.h中的OPENSSLDIR宏一样简单:
$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?
这里有更多信息可以帮助填补其他Stack Overflow问题的空白.这取决于您使用的OpenSSL安装.
这是简短的答案……图书馆和程序在OPENSSLDIR中寻找openssl.cnf. 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; }
… 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.
在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可能没有安装在打包器所设想的目录中.我甚至在Windows机器上看到过像/usr/local这样的Unix目录.
对于Windows,您最安全的选择可能是设置OPENSSL_CONF环境变量来覆盖损坏的路径和路径处理错误.
另外,我不知道在运行时为您提供有效目录的CONF_ *或NCONF_ * API调用.这里,有效目录将是配置目录以及OPENSSL_CONF覆盖等内容.现在在OpenSSL用户列表中打开:Get effective OPENSSLDIR path at runtime?