如何确定 openssl.cnf 的默认位置? [英] How to determine the default location for openssl.cnf?

查看:41
本文介绍了如何确定 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 变量是空的.

一个糟糕的选择

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

  1. $OPENSSL_CONF 变量已填充,文件存在
  2. /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.cload_configcnf 的 OpenSSL 源代码中> 是 NULL(即没有 -config 选项或 OPENSSL_CONF envar).当 cnfNULL 且没有覆盖时,则使用 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:

  1. $OPENSSL_CONF variable is populated, and file exists
  2. /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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆