bash 如何确定 openssl.cnf 的默认位置?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37035300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:16:23  来源:igfitidea点击:

How to determine the default location for openssl.cnf?

bashopenssl

提问by Jeff Puckett

Background

背景

I'm writing a bash script that will use openssl to generate a certificate signing request with X509v3 extension compliantsubject alternative names.

我正在编写一个 bash 脚本,该脚本将使用 openssl 生成具有X509v3 扩展兼容主题替代名称的证书签名请求。

Since there's no command line option for this, a solutionhas been to use the -configoption in conjunction with the -reqextsoption by appending the SAN values inline to the default configuration file.

由于没有用于此的命令行选项,因此解决方案是通过将 SAN 值内联附加到默认配置文件来将该-config选项与该-reqexts选项结合使用。

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

Question

My problem is portability. While a similar questionassures 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.

我的问题是便携性。虽然一个类似的问题让我确信这在我的 Ubuntu 环境中有效,因为默认配置文件是/etc/ssl/openssl.cnf,但不幸的是这不会在任何地方都有效,Windows 就是一个明显的例子。

How do I programmaticallydetermine the full path to the openssl defaultconfiguration file?

如何以编程方式确定 openssl默认配置文件的完整路径?

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 filenameor any specified in the OPENSSL_CONF environment variable.

-config filename
这允许指定备用配置文件,这会覆盖编译时文件名或在 OPENSSL_CONF 环境变量中指定的任何文件名

I've read the config documentationand 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_CONFvariable is empty.

此外,我的$OPENSSL_CONF变量是空的。

A Bad Alternative

一个糟糕的选择

Currently my script checks these conditions, and uses the first one that evaluates to true:

目前我的脚本检查这些条件,并使用第一个评估为真的条件:

  1. $OPENSSL_CONFvariable is populated, and file exists
  2. /etc/ssl/openssl.cnfexists
  1. $OPENSSL_CONF变量已填充,文件存在
  2. /etc/ssl/openssl.cnf存在

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.

如果这些都不是真的,那么它包含标准配置的副本。这是不可取的,因为它实际上会覆盖客户端建立的自定义设置。我想完全使用环境的条件,简单地添加SAN部分作为附录。

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.

我可以使用常见嫌疑人的路径甚至系统搜索来进一步扩展这条链。但是如果存在多个,那么我无法保证 openssl 实际上使用哪个作为默认值。

采纳答案by jww

How do I programmatically determine the full path to the openssl default configuration file?

如何以编程方式确定 openssl 默认配置文件的完整路径?

Programmatically, its as easy as using the OPENSSLDIRmacro from opensslconf.h:

以编程方式,它就像使用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"


How to determine the default location for openssl.cnf?

如何确定 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.

这里有更多信息可以帮助填补其他 Stack Overflow 问题中的空白。这取决于您使用的 OpenSSL 安装。

Here's the short answer... The library and programs look for openssl.cnfin OPENSSLDIR. OPENSSLDIRis a configure option, and its set with --openssldir.

这是简短的答案......库和程序openssl.cnfOPENSSLDIR. OPENSSLDIR是一个配置选项,它用--openssldir.

I'm on a MacBook with 3 different OpenSSL's (Apple's, MacPort's and the one I build):

我在一台装有 3 个不同 OpenSSL(Apple、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"

Here's the longer answer... It is kind of buried in OpenSSL source code for apps.c, load_configand what happens when cnfis NULL(i.e., no -configoption or OPENSSL_CONFenvar). When cnfis NULLand no overrides, then OPENSSLDIRis used.

这里的较长答案......这是一种埋在OpenSSL的源代码apps.cload_config并在会发生什么cnfNULL(即没有-config选项或OPENSSL_CONFENVAR)。当cnfisNULL且没有覆盖时,则OPENSSLDIR使用then 。

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.

...这在我的 Ubuntu 环境中有效,因为默认配置文件是/etc/ssl/openssl.cnf,不幸的是这不适用于任何地方,Windows 就是一个明显的例子。

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 .\util\copy.pl line 39" on).

在 Windows 上,这对您来说可能仍然是一个问题。如果您自己从源代码构建 OpenSSL,您应该没问题;对其在 Windows 中的长文件名处理取模(另请参阅问题 #4490:“nmake install”失败“目标必须是 .\util\copy.pl line 39 上的目录”)。

Folks like Shinning Light and Win32 OpenSSLprovide installers, and OpenSSL may notbe installed in the directory the packager envisioned. I've even seen Unix directories like /usr/localappear on Windows machines.

Shinning Light 和 Win32 OpenSSL 这样的人提供了安装程序,而 OpenSSL可能没有安装在打包程序设想的目录中。我什至看到 Unix 目录/usr/local出现在 Windows 机器上。

For Windows, your safest bet is probably set the OPENSSL_CONFenvironmental variable to override broken paths and path handling bugs.

对于 Windows,您最安全的选择可能是设置OPENSSL_CONF环境变量以覆盖损坏的路径和路径处理错误。



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_CONFoverrides. Now open on the OpenSSL User list: Get effective OPENSSLDIR path at runtime?

此外,我不知道在运行时为您提供有效目录的CONF_*NCONF_*API 调用。在这里,有效目录是配置目录加上OPENSSL_CONF覆盖之类的东西。现在在 OpenSSL 用户列表上打开:在运行时获取有效的 OPENSSLDIR 路径?

回答by Nicolas Bouvrette

As mentioned in one of the comments, the easy answer should be to find the path using the following command:

正如其中一条评论中提到的,简单的答案应该是使用以下命令找到路径:

openssl version -d

If this doesn't work, you could presume that OpenSSL is not correctly configured, or at least doesn't have the configuration you need. Here is an example in Node.js on how you could get the location of openssl.cnf:

如果这不起作用,您可以假定 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);
})();