How to determine the default location for openssl.cnf?

Background

I am writing a bash script that will use openssl to generate a certificate signing request with alternative subject names compatible with the X509v3 extension.

Since there is no command line option for this, the solution was to use the -config option in conjunction with the -reqexts option, -reqexts 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]\nsubjectAltName=DNS:example.com,DNS:www.example.com")) -out domain.csr 

Question

My problem is mobility. Although a similar question assures me that this works in my Ubuntu environment, because the default configuration file is /etc/ssl/openssl.cnf , unfortunately this will not work everywhere, and Windows is an obvious example.

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

What i tried

There's a clear hint in the documentation

-config file name
this allows you to specify an alternative configuration file, overrides the name of the compilation time file or any other specified in the environment variable OPENSSL_CONF.

I read the configuration documentation and searched for the source code , but I can’t find the mechanism by which it chooses where to load the default configuration file “compile time”. If I could find this, then I would prefer to load it as a variable into a script rather than a hard-coded path.

Moreover, my $OPENSSL_CONF variable is empty.

Bad alternative

My script is currently checking these conditions and using the first one, which evaluates to true:

  1. The variable $OPENSSL_CONF full and the file exists
  2. /etc/ssl/openssl.cnf exists

If none of them is true, then it includes a copy of the standard configuration. This is undesirable because it actually overrides the user preferences set by the client. I want to make full use of the environment and just add the SAN partition as an add-on.

I could further expand this chain with the usual suspects or even system searches. But if there are several, then I'm not sure that openssl is used by default.

+8
source share
2 answers

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

Programmatically, its as easy as using the OPENSSLDIR macro 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 is more information to help fill in the gaps from another question. It depends on the OpenSSL installation you are using.

Here is a short answer ... The library and programs look for openssl.cnf in OPENSSLDIR . OPENSSLDIR is a configuration option that is installed using --openssldir .

I am on a MacBook with 3 different OpenSSLs (Apple, MacPort and the one I'm building):

 # 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 a longer answer ... It’s like apps.c in the OpenSSL source code for apps.c , load_config and what happens when cnf is NULL (i.e., the -config option or the OPENSSL_CONF envar option). When cnf is NULL and has no overrides, then OPENSSLDIR 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\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 will not work everywhere and Windows is an obvious example.

This may still be a problem for you on Windows. You should be fine if you yourself build OpenSSL from source; modulo their processing of long file names in Windows (see also issue No. 4490: “nmake installation fails.” The destination must be a directory in. \ util \ copy.pl line 39 "on ).

People like Shinning Light and Win32 OpenSSL provide installers, and OpenSSL may not install in the directory provided by the packer. I even saw Unix directories like /usr/local on Windows computers.

For Windows, your safest bet is probably to have the OPENSSL_CONF environment variable OPENSSL_CONF to override broken paths and path processing errors.


Also, I don't know about CONF_* API CONF_* or NCONF_* which gives you an efficient directory at runtime. An effective directory here would be a configuration directory, plus things like OPENSSL_CONF overrides. Now open the list of OpenSSL users: get the efficient OPENSSLDIR path at runtime?

+6
source

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

 openssl version -d 

If this does not work, you can assume that OpenSSL is configured incorrectly or at least does not have the necessary configuration. Here is an example in Node.js on how you can get the openssl.cnf location:

 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); })(); 
0
source

All Articles