openssl "unable to find 'distinguished_name' in config"

I get the following error from openssl req:

unable to find 'distinguished_name' in config
problems making Certificate Request
41035:error:0E06D06C:configuration file routines:NCONF_get_string:no value:/SourceCache/OpenSSL098/OpenSSL098-52.30.1/src/crypto/conf/conf_lib.c:329:group=req name=distinguished_name

My understanding is that this is the "Subject" that it can't find… however, I am specifying that:

openssl req -new \
    -key "$PRIVATE_KEY" \
    -sha256 \
    -config "$OPTIONS_FILE" \
    -subj "/C=US/ST=California/L=San Francisco/O=ACME, Inc./CN=*.*.$DOMAIN/" \
    -out "$CSR_FILENAME"

The manual's only suggestion is that the config file doesn't exist; I can cat "$OPTIONS_FILE", so it's definitely there, and the error isn't preceded by the error the manual notes it would be preceded by if this were the case, so I'm pretty sure openssl sees the config file.

My config file contains the following:

[req]
req_extensions = v3_req

[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.*.example.com 

…which is pretty much literally the example in the docs.

What am I doing wrong here?


Solution 1:

Near as I can tell, -config is overriding some sort of internal config; if you see the "EXAMPLES" section for the man page for openssl req, it shows an example of a config file with distinguished_name in it. On a hunch, I added the following to my config:

[req]
…
distinguished_name = req_distinguished_name

[req_distinguished_name]
# empty.

Thus, my entire config looked something like

[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name

[req_distinguished_name]

[v3_req]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.*.${DOMAIN}

(Note that here, ${DOMAIN} is not literal; you should replace it with your DNS domain name; I create this file in a bash script with cat >"$OPTIONS_FILE" <<EOF, followed by the above, followed by EOF)

openssl req … -subj <my subject> -config <that file> … then took my subject from the command line. For those interested, the entire command ended up looking like:

openssl req -new \
    -key "$PRIVATE_KEY" \
    -sha256 \
    -config "$OPTIONS_FILE" \
    -subj "/C=US/ST=California/L=San Francisco/O=My Company, Inc./CN=*.*.$DOMAIN/" \
    -out "$CSR_FILENAME"

As of this posting, my understanding is that SHA-1 is deprecated¹ for X.509 certs, hence -sha256 (which is an undocumented flag…), and subjectAltName is becoming required², hence the need for the config. The only additional gotcha that I know of in order to generate a best-practice CSR to the above is that you should use a RSA key size of at least 2048 bits (if you're using RSA, which I am); you must specify the size to the openssl genrsa command as the current default is insecure.

¹While not broken at the time I'm writing this, people feel that it is only a matter of time. See "Gradually sunsetting SHA1"
²Using CN for the domain-name is no longer recommended; I'm not sure when/if browsers are planning to deprecate this. "Move away from including and checking strings that look like domain names in the subject's Common Name.", RFC 6125
Note: I am less certain about the "correct" value of keyUsage.

Solution 2:

I had the same problem and found the response here:

https://www.citrix.com/blogs/2015/04/10/how-to-create-a-csr-for-a-san-certificate-on-netscaler/

The config file looks like this:

[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = VA
L = SomeCity
O = MyCompany
OU = MyDivision
CN = www.company.com
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = www.company.com
DNS.2 = company.com
DNS.3 = www.company.net 
DNS.4 = company.net 

And then:

openssl req -new -key private.key -sha256 -nodes -config openssl.conf -out certificate.csr