OpenVPN / easy-rsa

easy-rsa - Simple shell based CA utility
Other
4.02k stars 1.19k forks source link

EasyRSA Behavior Change - 3.0.8 - 3.2.0 - EASYRSA_REQ_CN / --req-cn /--subject-alt-name #1148

Closed joubertdj closed 6 days ago

joubertdj commented 4 months ago

I have been using easyrsa for a while now ... and maybe I have been using it "incorrectly", the result was actually precisely what I wanted. For several system clients I generate a specific CA, with unique CNs, and then the different systems that needs to intercommunicate I generate certificates for each of the systems, all with unique CNs and unique SAN (IPs DNS, etc.).

Previously, when I had a vars file with EASYRSA_REQ_CN and EASYRSA_BATCH set, then the build-ca command would take that CN as the CA CN name. And when I then run something like (just an example):

./easyrsa --req-cn="Supercompany - Loc X - Subsystem X" --subject-alt-name="IP:127.0.0.1, DNS:localhost" gen-req "sysb" nopass

I would get a private key of "sysb.key", a CSR of "sysb.req, and then I could sign it ... and the SAN will also be in tack, and the CN name will be as it was required within the sysb.crt file ... however, this behavior is now different in 3.2.0.

When I tried it as previously ... I got regular errors of: 'gen-req' does not support setting an external commonName

What is the correct way of obtaining the previous behavior? I tried removing the EASYRSA_REQ_CN but then things gets even weirder with the key being something like: "--req-cn="Supercompany - Loc X - Subsystem X".key"

TinCanTech commented 4 months ago

@joubertdj Please show the command and output using the --verbose switch.

joubertdj commented 4 months ago

@TinCanTech : Thanks for the quick response. I was able to add the SAN stuff via the "--san" option when doing a "sign-req". But the CN I am still "stumped" ...

The command: ./easyrsa --req-cn="Trapeze South Africa - TSA-HTE - Router1 Server" --verbose gen-req "router1" nopass The output of the above command with "--verbose" is:

select_vars: PWD/pki/vars 
Using Easy-RSA 'vars' configuration:
* /mnt/c/Data/Work/Trapeze/Projects/2024/TSA-HTE/Backups/Certificate Authority/Current/pki/vars
source_vars: CLEAN '/mnt/c/Data/Work/Trapeze/Projects/2024/TSA-HTE/Backups/Certificate Authority/Current/pki/vars'
source_vars: sourced OK '/mnt/c/Data/Work/Trapeze/Projects/2024/TSA-HTE/Backups/Certificate Authority/Current/pki/vars'
mutual_exclusions: COMPLETED
 > EASYRSA_EXT_DIR: /mnt/c/Data/Work/Trapeze/Projects/2024/TSA-HTE/Backups/Certificate Authority/Current/x509-types
> EASYRSA_SSL_CONF: /mnt/c/Data/Work/Trapeze/Projects/2024/TSA-HTE/Backups/Certificate Authority/Current/openssl-easyrsa.cnf
  > EASYRSA_TOOLS_LIB: undefined
  locate_support_files: COMPLETED
  verify_ssl_lib():
Using SSL:
* openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
  verify_working_env: BEGIN
  secure_session: CREATED: /mnt/c/Data/Work/Trapeze/Projects/2024/TSA-HTE/Backups/Certificate Authority/Current/pki/ba92208a
  write_easyrsa_ssl_cnf_tmp: SSL config EXISTS
  write_easyrsa_ssl_cnf_tmp: SSL config IGNORED
  easyrsa_mktemp: ssl_cnf_tmp OK: /mnt/c/Data/Work/Trapeze/Projects/2024/TSA-HTE/Backups/Certificate Authority/Current/pki/ba92208a/temp.0.1
  write_easyrsa_ssl_cnf_tmp: SSL config using temp-file
  verify_algo_params: Params verified for algo 'rsa'
  verify_working_env: COMPLETED Handover-to: gen-req

EasyRSA version 3.2.0

Error
-----
Option conflict --req-cn:
* 'gen-req' does not support setting an external commonName

  mktemp_counter: 1 uses
  remove_secure_session: DELETED: /mnt/c/Data/Work/Trapeze/Projects/2024/TSA-HTE/Backups/Certificate Authority/Current/pki/ba92208a
  Exit: Known errors = true
joubertdj commented 4 months ago

When I try to use the sign-req for the --req-cn it also complains about that ...

TinCanTech commented 4 months ago

@joubertdj relax .. you can leave this open, for now.

TinCanTech commented 4 months ago

@joubertdj Thanks.

First: Upgrading from v3.0.8 to v3.2.0-D is understanably difficult.

With regard to your SAN use, you have figured out the solution. :+1:

With regard to your use of --req-cn, that is no longer supported.

The commonName must be the same as the file_name_base. The exception is build-ca, which allows setting the CA commonName.

This change was made in commit: 7227909

I will expand on this decision later.

However, you have to accept that your use of --req-cn is obscure and bizarre.

joubertdj commented 4 months ago

@TinCanTech : Hehehe ... yeah, please don't ask why I never used the FQDN ... I think I "did" at one point but when I placed an "explanation" instead of FQDN it "looked better" (or something like that ... there was also some RFC that indicated CN's aren't really used/considered but the SAN is the priority (this works with most/all our systems ... ))

Ah well, thanks, I will just have to amend though then ...

VVD commented 3 months ago

My usage is more easy:

/usr/local/bin/easyrsa gen-req "${USER}" nopass batch
/usr/local/bin/easyrsa --batch --passin=pass:"$CA_PASSWORD" sign-req client "${USER}"

but it is broken now too with same error:

EasyRSA version 3.2.0

Error
-----
Option conflict --req-cn:
* 'gen-req' does not support setting an external commonName
# /usr/local/bin/easyrsa --verbose gen-req USERNAME nopass batch
  # select_vars: PWD/pki/vars
Using Easy-RSA 'vars' configuration:
* /usr/local/etc/openvpn/pki/vars
  # source_vars: CLEAN '/usr/local/etc/openvpn/pki/vars'
  # source_vars: sourced OK '/usr/local/etc/openvpn/pki/vars'
  # mutual_exclusions: COMPLETED
  # > EASYRSA_EXT_DIR: /usr/local/share/easy-rsa/x509-types
  # > EASYRSA_SSL_CONF: /usr/local/etc/openvpn/pki/openssl-easyrsa.cnf
  # > EASYRSA_TOOLS_LIB: undefined
  # locate_support_files: COMPLETED
  # verify_ssl_lib():
Using SSL:
* openssl OpenSSL 1.1.1w-freebsd  11 Sep 2023
  # verify_working_env: BEGIN
  # secure_session: CREATED: /usr/local/etc/openvpn/pki/23c4b028
  # write_easyrsa_ssl_cnf_tmp: SSL config EXISTS
  # write_easyrsa_ssl_cnf_tmp: SSL config IGNORED
  # easyrsa_mktemp: ssl_cnf_tmp OK: /usr/local/etc/openvpn/pki/23c4b028/temp.0.1
  # write_easyrsa_ssl_cnf_tmp: SSL config using temp-file
  # verify_algo_params: Params verified for algo 'ed'
  # verify_working_env: COMPLETED Handover-to: gen-req

EasyRSA version 3.2.0

Error
-----
Option conflict --req-cn:
* 'gen-req' does not support setting an external commonName

  # mktemp_counter: 1 uses
  # remove_secure_session: DELETED: /usr/local/etc/openvpn/pki/23c4b028
  # Exit: Known errors = true

It'm using /usr/local/etc/openvpn/pki/vars with EASYRSA_REQ_CN set to our FQDN of the OpenVPN server:

# grep EASYRSA_REQ_CN /usr/local/etc/openvpn/pki/vars
set_var EASYRSA_REQ_CN          "hostname.domain.name"
VVD commented 3 months ago

Commented in gen_req():

#       [ "$EASYRSA_REQ_CN" = ChangeMe ] || user_error "\
#Option conflict --req-cn:
#* '$cmd' does not support setting an external commonName"

Got same error, but for sign_req, commented in sign_req():

#       [ "$EASYRSA_REQ_CN" = ChangeMe ] || user_error "\
#Option conflict --req-cn:
#* '$cmd' does not support setting an external commonName"

After this my commands work as before (probably).

TinCanTech commented 3 months ago

It is good to see that EasyRSA code is easy to customise.

Version 3.1.7 also has the functionality that you desire.

Version 3.2.0 is a development snapshot.

joubertdj commented 3 months ago

@TinCanTech : This was the RFC I was referring to that indicated that the CN isn't preferred anymore, but SAN: https://www.rfc-editor.org/rfc/rfc2818.html, this portion:

"If a subjectAltName extension of type dNSName is present, that MUST be used as the identity. Otherwise, the (most specific) Common Name field in the Subject field of the certificate MUST be used. Although the use of the Common Name is existing practice, it is deprecated and Certification Authorities are encouraged to use the dNSName instead."

TinCanTech commented 3 months ago

@joubertdj Thank you, I am aware of RFC2818.

TinCanTech commented 3 months ago

@VVD Please test #1168

I hope it satisfies your usage.

VVD commented 3 months ago

@VVD Please test #1168

I hope it satisfies your usage.

This patch does not apply to 3.2.0, so I made my own based on it:

--- easyrsa.orig        2024-05-18 12:20:59 UTC
+++ easyrsa
@@ -2132,14 +2132,12 @@ Run easyrsa without commands for usage and commands."
                ssl_batch=1
        fi

-       # Prohibit --req-cn
-       [ "$EASYRSA_REQ_CN" = ChangeMe ] || user_error "\
-Option conflict --req-cn:
-* '$cmd' does not support setting an external commonName"
+       # if EASYRSA_REQ_CN has NOT been changed
+       # then use file_name_base
+       if [ "$EASYRSA_REQ_CN" = ChangeMe ]; then
+               export EASYRSA_REQ_CN="$file_name_base"
+       fi

-       # Enforce commonName
-       export EASYRSA_REQ_CN="$file_name_base"
-
        # Output files
        key_out="$EASYRSA_PKI/private/${file_name_base}.key"
        req_out="$EASYRSA_PKI/reqs/${file_name_base}.req"
@@ -2282,14 +2280,14 @@ expected 2, got $# (see command help for usage)"
        crt_out="$EASYRSA_PKI/issued/$file_name_base.crt"
        shift 2

-       # Prohibit --req-cn
-       [ "$EASYRSA_REQ_CN" = ChangeMe ] || user_error "\
-Option conflict --req-cn:
+       # Ignore --req-cn, CN is set by request
+       # To change the CN use --new-subject='/CN=foo'
+       if [ "$EASYRSA_REQ_CN" != ChangeMe ]; then
+               warn "\
+Ignoring Option conflict --req-cn:
 * '$cmd' does not support setting an external commonName"
+       fi

-       # Enforce commonName
-       export EASYRSA_REQ_CN="$file_name_base"
-
        # Check optional subject
        force_subj=
        while [ "$1" ]; do
@@ -2742,10 +2740,7 @@ Warning!
 An inline file for name '$name' already exists:
 * $inline_out"

-       # Set commonName
-       [ "$EASYRSA_REQ_CN" = ChangeMe ] || user_error "\
-Option conflict --req-cn:
-* '$cmd' does not support setting an external commonName"
+       # 'commonName' has already been set for 'gen-req'

        # Set to modify sign-req confirmation message
        do_build_full=1
@@ -2756,7 +2751,7 @@ Option conflict --req-cn:
        # Require --copy-ext
        export EASYRSA_CP_EXT=1

-       # Must be reset for nested commmands
+       # CN Must be reset for nested sign_req
        export EASYRSA_REQ_CN=ChangeMe

        # Sign it
TinCanTech commented 3 months ago

This patch does not apply to 3.2.0

Sorry about that, I raised it against master branch.

Having taken a close look at how --req-cn can/should be used, I am reasonably happy to re-enable its use for v3.2.1.

TinCanTech commented 3 months ago

Linking: #1170 - Resolves use of --req-cn.

VVD commented 3 months ago
# /usr/local/bin/easyrsa --verbose --batch --passin=pass:${CA_PASS} sign-req client ${USER}
  # select_vars: EASYRSA_VARS_FILE
Using Easy-RSA 'vars' configuration:
* /usr/local/etc/openvpn/pki/vars_120
  # source_vars: CLEAN '/usr/local/etc/openvpn/pki/vars_120'
  # source_vars: sourced OK '/usr/local/etc/openvpn/pki/vars_120'
  # mutual_exclusions: COMPLETED
  # > EASYRSA_EXT_DIR: /usr/local/share/easy-rsa/x509-types
  # > EASYRSA_SSL_CONF: /usr/local/etc/openvpn/pki/openssl-easyrsa.cnf
  # > EASYRSA_TOOLS_LIB: undefined
  # locate_support_files: COMPLETED
  # verify_ssl_lib():
Using SSL:
* openssl OpenSSL 1.1.1w-freebsd  11 Sep 2023
  # verify_working_env: BEGIN
  # secure_session: CREATED: /usr/local/etc/openvpn/pki/5aeedab2
  # write_easyrsa_ssl_cnf_tmp: SSL config EXISTS
  # write_easyrsa_ssl_cnf_tmp: SSL config IGNORED
  # easyrsa_mktemp: ssl_cnf_tmp OK: /usr/local/etc/openvpn/pki/5aeedab2/temp.0.1
  # write_easyrsa_ssl_cnf_tmp: SSL config using temp-file
  # verify_algo_params: Params verified for algo 'ed'
  # verify_working_env: COMPLETED Handover-to: sign-req

WARNING
=======
Ignoring Option conflict --req-cn:
* 'sign-req' does not support setting an external commonName

  # > easyrsa_openssl - BEGIN req
  # escape_hazard: RUN-ONCE
  # escape_hazard: REPLACED by heredoc expansion
  # escape_hazard: ABANDONED
  # expand_ssl_config: IGNORED
  # > easyrsa_openssl: No Safe SSL conf, FALLBACK to default
  # check_serial_unique: unique_serial=true
  # easyrsa_mktemp: ext_tmp OK: /usr/local/etc/openvpn/pki/5aeedab2/temp.1.1
  # sign_req: Generated extensions file OK
  # easyrsa_mktemp: crt_out_tmp OK: /usr/local/etc/openvpn/pki/5aeedab2/temp.2.1
  # > easyrsa_openssl - BEGIN ca
  # escape_hazard: RUN-ONCE
  # escape_hazard: REPLACED by heredoc expansion
  # escape_hazard: ABANDONED
  # expand_ssl_config: IGNORED
  # > easyrsa_openssl: No Safe SSL conf, FALLBACK to default
Using configuration from /usr/local/etc/openvpn/pki/5aeedab2/temp.0.1
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'hostname.domain.name'
ERROR:There is already a certificate for /CN=hostname.domain.name
The matching entry has the following details
Type          :Valid
Expires on    :261015175821Z
Serial Number :01
File name     :unknown
Subject Name  :/CN=hostname.domain.name

Easy-RSA error:

easyrsa_openssl - Command has failed:
* openssl ca -utf8 -batch -in /usr/local/etc/openvpn/pki/reqs/${USER}.req -out /usr/local/etc/openvpn/pki/5aeedab2/temp.2.1 -extfile /usr/local/etc/openvpn/pki/5aeedab2/temp.1.1 -passin pass:${CA_PASS} -days 120

EasyRSA Version Information
Version:     3.2.0
Generated:   Sat May 18 07:20:59 CDT 2024
SSL Lib:     OpenSSL 1.1.1w-freebsd  11 Sep 2023
Git Commit:  76115cc7add1f5ffc78b54cdcbc843c2cc075089
Source Repo: https://github.com/OpenVPN/easy-rsa
Host: 3.2.0 | nix | FreeBSD | /usr/local/bin/bash
  # mktemp_counter: 3 uses
  # remove_secure_session: DELETED: /usr/local/etc/openvpn/pki/5aeedab2
  # Exit: Final Fail = true

Patch:

--- easyrsa.orig
+++ easyrsa
@@ -2134,9 +2134,7 @@ Run easyrsa without commands for usage and commands."

        # if EASYRSA_REQ_CN has NOT been changed
        # then use file_name_base
-       if [ "$EASYRSA_REQ_CN" = ChangeMe ]; then
-               export EASYRSA_REQ_CN="$file_name_base"
-       fi
+       export EASYRSA_REQ_CN="$file_name_base"

        # Output files
        key_out="$EASYRSA_PKI/private/${file_name_base}.key"
TinCanTech commented 3 months ago

Please try git/master as-of commit 01dfe77c02c1ec89f9a83431eb11090551b79cac

VVD commented 3 months ago

Please try git/master as-of commit 01dfe77

Not fixed:

# ./easyrsa --batch '--passin=pass:${CA_PASS}' sign-req client ${USER}
Using Easy-RSA 'vars' configuration:
* /usr/local/etc/openvpn/pki/vars
Using configuration from /usr/local/etc/openvpn/pki/5a5db864/temp.1.1
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'hostname.domain.name'
ERROR:There is already a certificate for /CN=hostname.domain.name
The matching entry has the following details
Type          :Valid
Expires on    :261015175821Z
Serial Number :01
File name     :unknown
Subject Name  :/CN=hostname.domain.name

Easy-RSA error:

easyrsa_openssl - Command has failed:
* openssl ca -utf8 -batch -in /usr/local/etc/openvpn/pki/reqs/${USER}.req -out /usr/local/etc/openvpn/pki/5a5db864/temp.3.1 -extfile /usr/local/etc/openvpn/pki/5a5db864/temp.2.1 -passin pass:${CA_PASS} -days 3650

EasyRSA Version Information
Version:     ~VER~
Generated:   ~DATE~
SSL Lib:     OpenSSL 1.1.1w-freebsd  11 Sep 2023
Git Commit:  ~GITHEAD~
Source Repo: https://github.com/OpenVPN/easy-rsa
Host: dev | nix | FreeBSD | /usr/local/bin/bash

Check near hostname.domain.name - it must be ${USER}. With my patch it have correct value.

VVD commented 1 week ago

This bug is still here in 3.2.1:

/usr/local/bin/easyrsa --batch '--passin=pass:********' sign-req client easyrsa321test
Using Easy-RSA 'vars' configuration:
* /usr/local/etc/openvpn/pki/vars
Using configuration from /usr/local/etc/openvpn/pki/e6c8cb62/temp.1.1
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'hostname.domain.name'
ERROR:There is already a certificate for /CN=hostname.domain.name
The matching entry has the following details
Type          :Valid
Expires on    :261015175821Z
Serial Number :01
File name     :unknown
Subject Name  :/CN=hostname.domain.name

Easy-RSA error:

easyrsa_openssl - Command has failed:
* openssl ca -utf8 -batch -in /usr/local/etc/openvpn/pki/reqs/easyrsa321test.req -out /usr/local/etc/openvpn/pki/e6c8cb62/temp.3
.1 -extfile /usr/local/etc/openvpn/pki/e6c8cb62/temp.2.1 -passin pass:******** -days 3650

EasyRSA Version Information
Version:     3.2.1
Generated:   Fri Sep 13 13:04:18 CDT 2024
SSL Lib:     OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)
Git Commit:  3f60a68702713161ab44f9dd80ce01f588ca49ac
Source Repo: https://github.com/OpenVPN/easy-rsa
Host: 3.2.1 | nix | FreeBSD | /usr/local/bin/bash

Patch:

@@ -2212,31 +2212,29 @@ Run easyrsa without commands for usage and commands."
 # gen-req and key backend:
 gen_req() {
        # pull filename, use as default interactive CommonName
        [ "$1" ] || user_error "\
 Error: gen-req must have a file-name-base as the first argument.
 Run easyrsa without commands for usage and commands."

        file_name_base="$1"
        shift # scrape off file-name-base

        # Set ssl batch mode as required
        [ "$EASYRSA_BATCH" ] && ssl_batch=1

        # Set commonName
-       if [ "$EASYRSA_REQ_CN" = ChangeMe ]; then
                export EASYRSA_REQ_CN="$file_name_base"
-       fi

        # create local SSL cnf
        write_easyrsa_ssl_cnf_tmp

        # Output files
        key_out="$EASYRSA_PKI/private/${file_name_base}.key"
        req_out="$EASYRSA_PKI/reqs/${file_name_base}.req"

        # function opts support
        while [ "$1" ]; do
                case "$1" in
                        text)
                                text=1
                                ;;
mandree commented 1 week ago

@VVD: I tried the script below but cannot reproduce the error on 3.2.1:

[mandree@freeryzen /usr/ports/security/easy-rsa]$ cat test.sh 
#!/bin/sh
set -eux
export EASYRSA_PKI="$(mktemp -d)"
easyrsa --batch init-pki
echo 'set_var EASYRSA_REQ_CN hostname.example.org' >"$EASYRSA_PKI/vars"
easyrsa --batch build-ca nopass 
easyrsa gen-req "$USER" nopass batch
easyrsa --batch --passin=pass:asdfassdf sign-req client "$USER"

Please extend the script such that we can reproduce the issue.

VVD commented 1 week ago
# grep -vE '^(#|$)' /usr/local/etc/openvpn/pki/vars
if [ -z "$EASYRSA_CALLER" ]; then
        echo "You appear to be sourcing an Easy-RSA *vars* file. This is" >&2
        echo "no longer necessary and is disallowed. See the section called" >&2
        echo "*How to use this file* near the top comments for more details." >&2
        return 1
fi
set_var EASYRSA_PKI             "/usr/local/etc/openvpn/pki"
set_var EASYRSA_REQ_COUNTRY     "XX"
set_var EASYRSA_REQ_PROVINCE    "XXXXXX"
set_var EASYRSA_REQ_CITY        "XXXXXX"
set_var EASYRSA_REQ_ORG         "XXXXXX"
set_var EASYRSA_REQ_EMAIL       "mail@domain.name"
set_var EASYRSA_REQ_OU          "XXX"
set_var EASYRSA_REQ_CN          "hostname.domain.name"
set_var EASYRSA_KEY_SIZE        4096
set_var EASYRSA_ALGO            ed
set_var EASYRSA_CURVE           ed25519
set_var EASYRSA_CA_EXPIRE       3650
set_var EASYRSA_CERT_EXPIRE     3650
set_var EASYRSA_CRL_DAYS        3650
set_var EASYRSA_CERT_RENEW      3650
set_var EASYRSA_DIGEST          "sha512"
# /usr/local/bin/easyrsa gen-req easyrsa321test nopass batch
Using Easy-RSA 'vars' configuration:
* /usr/local/etc/openvpn/pki/vars
-----

Notice
------
Private-Key and Public-Certificate-Request files created.
Your files are:
* req: /usr/local/etc/openvpn/pki/reqs/easyrsa321test.req
* key: /usr/local/etc/openvpn/pki/private/easyrsa321test.key
# /usr/local/bin/easyrsa --batch '--passin=pass:********' sign-req client easyrsa321test
Using Easy-RSA 'vars' configuration:
* /usr/local/etc/openvpn/pki/vars
Using configuration from /usr/local/etc/openvpn/pki/e6c8cb62/temp.1.1
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'hostname.domain.name'
ERROR:There is already a certificate for /CN=hostname.domain.name
The matching entry has the following details
Type          :Valid
Expires on    :261015175821Z
Serial Number :01
File name     :unknown
Subject Name  :/CN=hostname.domain.name

Easy-RSA error:

easyrsa_openssl - Command has failed:
* openssl ca -utf8 -batch -in /usr/local/etc/openvpn/pki/reqs/easyrsa321test.req -out /usr/local/etc/openvpn/pki/e6c8cb62/temp.3
.1 -extfile /usr/local/etc/openvpn/pki/e6c8cb62/temp.2.1 -passin pass:******** -days 3650

EasyRSA Version Information
Version:     3.2.1
Generated:   Fri Sep 13 13:04:18 CDT 2024
SSL Lib:     OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)
Git Commit:  3f60a68702713161ab44f9dd80ce01f588ca49ac
Source Repo: https://github.com/OpenVPN/easy-rsa
Host: 3.2.1 | nix | FreeBSD | /usr/local/bin/bash
mandree commented 1 week ago

@VVD Still not reproducing with the script below run under sh on FreeBSD 14.1-RELEASE-p3 amd64 with easy-rsa-3.2.1,1 from ports. Do you run this as root or in some other way such that your $EASYRSA_PKI is writable? Do you have libressl or openssl installed from ports?

#!/bin/sh
set -eux
export EASYRSA_PKI="$(mktemp -d)"
easyrsa --batch init-pki
cat <<'_EOF' >"$EASYRSA_PKI/vars"
set_var EASYRSA_REQ_COUNTRY     "XX"
set_var EASYRSA_REQ_PROVINCE    "XXXXXX"
set_var EASYRSA_REQ_CITY        "XXXXXX"
set_var EASYRSA_REQ_ORG         "XXXXXX"
set_var EASYRSA_REQ_EMAIL       "mail@example.org"
set_var EASYRSA_REQ_OU          "XXX"
set_var EASYRSA_REQ_CN          "hostname.example.org"
set_var EASYRSA_KEY_SIZE        4096
set_var EASYRSA_ALGO            ed
set_var EASYRSA_CURVE           ed25519
set_var EASYRSA_CA_EXPIRE       3650
set_var EASYRSA_CERT_EXPIRE     3650
set_var EASYRSA_CRL_DAYS        3650
set_var EASYRSA_CERT_RENEW      3650
set_var EASYRSA_DIGEST          "sha512"
_EOF
easyrsa --batch build-ca nopass 
easyrsa gen-req "$USER" nopass batch
easyrsa --batch --passin=pass:asdfassdf sign-req client "$USER"

Output:

[mandree@freeryzen /usr/ports/security/easy-rsa]$ sh test.sh 
+ mktemp -d
+ export 'EASYRSA_PKI=/tmp/tmp.Zz9XIAv68b'
+ easyrsa --batch init-pki

Notice
------
'init-pki' complete; you may now create a CA or requests.

Your newly created PKI dir is:
* /tmp/tmp.Zz9XIAv68b

Using Easy-RSA configuration:
* undefined
+ cat
+ easyrsa --batch build-ca nopass
Using Easy-RSA 'vars' configuration:
* /tmp/tmp.Zz9XIAv68b/vars

Notice
------
CA creation complete. Your new CA certificate is at:
* /tmp/tmp.Zz9XIAv68b/ca.crt

Create an OpenVPN TLS-AUTH|TLS-CRYPT-V1 key now: See 'help gen-tls'

Build-ca completed successfully.

+ easyrsa gen-req mandree nopass batch
Using Easy-RSA 'vars' configuration:
* /tmp/tmp.Zz9XIAv68b/vars
-----

Notice
------
Private-Key and Public-Certificate-Request files created.
Your files are:
* req: /tmp/tmp.Zz9XIAv68b/reqs/mandree.req
* key: /tmp/tmp.Zz9XIAv68b/private/mandree.key

+ easyrsa --batch '--passin=pass:asdfassdf' sign-req client mandree
Using Easy-RSA 'vars' configuration:
* /tmp/tmp.Zz9XIAv68b/vars
Using configuration from /tmp/tmp.Zz9XIAv68b/c8c058d6/temp.1.1
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'hostname.example.org'
Certificate is to be certified until Sep 22 13:48:35 2034 GMT (3650 days)

Write out database with 1 new entries
Database updated

Notice
------
Inline file created:
* /tmp/tmp.Zz9XIAv68b/inline/private/mandree.inline

Notice
------
Certificate created at:
* /tmp/tmp.Zz9XIAv68b/issued/mandree.crt
mandree commented 1 week ago

@VVD note in your logs there is this error report (3rd line) above what you try to fix.

The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'hostname.domain.name'
ERROR:There is already a certificate for /CN=hostname.domain.name
VVD commented 1 week ago

Do you run this as root or in some other way such that your $EASYRSA_PKI is writable?

From root.

Do you have libressl or openssl installed from ports?

OpenSSL from base only.

This config work for 8 years, added 277 users and it work fine with 3.1.7. As I already wrote this patch fixed the issue:

@@ -2212,31 +2212,29 @@ Run easyrsa without commands for usage and commands."
 # gen-req and key backend:
 gen_req() {
        # pull filename, use as default interactive CommonName
        [ "$1" ] || user_error "\
 Error: gen-req must have a file-name-base as the first argument.
 Run easyrsa without commands for usage and commands."

        file_name_base="$1"
        shift # scrape off file-name-base

        # Set ssl batch mode as required
        [ "$EASYRSA_BATCH" ] && ssl_batch=1

        # Set commonName
-       if [ "$EASYRSA_REQ_CN" = ChangeMe ]; then
                export EASYRSA_REQ_CN="$file_name_base"
-       fi

        # create local SSL cnf
        write_easyrsa_ssl_cnf_tmp

        # Output files
        key_out="$EASYRSA_PKI/private/${file_name_base}.key"
        req_out="$EASYRSA_PKI/reqs/${file_name_base}.req"

        # function opts support
        while [ "$1" ]; do
                case "$1" in
                        text)
                                text=1
                                ;;

@VVD note in your logs there is this error report (3rd line) above what you try to fix.

The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'hostname.domain.name'
ERROR:There is already a certificate for /CN=hostname.domain.name

I know - I used this info for write the patch.

mandree commented 1 week ago

So... it also works fine with 3.2.1 for me. And now? I think you best file a new issue once you have a way that others can reliably reproduce what you find to be a bug and what to me looks like your trying to generate a certificate you already have, which you do not want to clobber.

VVD commented 1 week ago

So... it also works fine with 3.2.1 for me. And now? I think you best file a new issue once you have a way that others can reliably reproduce what you find to be a bug and what to me looks like your trying to generate a certificate you already have, which you do not want to clobber.

Does the OpenVPN server work fully with the keys generated by your script? This is not in the script.

looks like your trying to generate a certificate you already have

Ofc I have certificate with name "hostname.domain.name" in pki - it was generated during prepare server's certificates for OpenVPN. If it uses "hostname.domain.name" for each certificate, then you won't be able to sign the second certificate.

mandree commented 1 week ago

You are wasting everybodys time by not explaining what you do, and then weasling out and adding more variables to the equation that was incomplete from the start.

For the last time before I ignore you for good, here and on FreeBSD:

Please write a or extend my script that I can run and that shows, on my computer,

If you mask your fields and that masking hides the bug, nobody will be able to help you.

To put it bluntly, if you cannot show the bug, then there is no bug, and no reason for anyone to accept the patch.

VVD commented 1 week ago

I don't understand what you're missing in my messages? I've provided all the command lines and all the messages from the script:

/usr/local/bin/easyrsa gen-req easyrsa321test nopass batch
/usr/local/bin/easyrsa --batch '--passin=pass:********' sign-req client easyrsa321test

And I provide patch to fix this bug.

You're not asking me to share my pki, are you?

My server configuration has been working for about 8 years now and I can't remember the exact command line for generating a server certificate, not to mention that they were created by easyrsa on a much older version and on FreeBSD 10.x. According to our documentation, the commands were as follows:

easyrsa init-pki
easyrsa build-ca
easyrsa gen-dh
easyrsa gen-req vpn.unislabs.com nopass
easyrsa sign-req server hostname.domain.name

Test on just created new pki: If create user with 3.1.7 message in console: commonName :ASN.1 12:'test1' If create user with 3.2.1 message in console: commonName :ASN.1 12:'hostname.domain.name'

# grep Subject: issued/test*.crt
issued/test1.crt:        Subject: CN=test1
issued/test2.crt:        Subject: CN=test2
issued/test3.crt:        Subject: CN=hostname.domain.name
issued/test4.crt:        Subject: CN=hostname.domain.name

Another manifestation of this bug:

# cat index.txt
V       340923162244Z           34DC2E0865281A037C4704DA3FB4A966        unknown /CN=test1
V       340923162258Z           370EBA0C35D32B0025821015CFFE1DEB        unknown /CN=test2
V       340923162352Z           041BB7EF2315EB19706F3AE0C59A7B22        unknown /CN=hostname.domain.name
V       340923162416Z           430F39AC894AEBE2D90FB3E1BA9FBA10        unknown /CN=hostname.domain.name

In index.txt it is impossible to see the list of users to whom certificates were issued, as well as which users' certificates were actually revoked and which were not.

If change in file pki/vars line set_var EASYRSA_REQ_CN "hostname.domain.name" with set_var EASYRSA_REQ_CN "ChangeMe" then it starts filling the field CN correctly:

# grep Subject: issued/test6.crt
        Subject: CN=test6
# grep test6 index.txt
V       340923164142Z           47A783F4A59B603E07791EA41BB5F5DA        unknown /CN=test6

This is the essence of the error: the correct value for the CN is set only if the value of the EASYRSA_REQ_CN variable is set to ChangeMe (/usr/local/bin/easyrsa):

       if [ "$EASYRSA_REQ_CN" = ChangeMe ]; then
                export EASYRSA_REQ_CN="$file_name_base"
       fi

or the variable EASYRSA_REQ_CN is not defined in vars (/usr/local/bin/easyrsa):

default_vars() {
…
        set_var EASYRSA_REQ_CN                  ChangeMe
…

One more test:

  1. Copied my current pki on test host.
  2. Removed all certs and keys except:
    ca.crt
    dh.pem
    ta.key
    issued/hostname.domain.name.crt
    private/ca.key
    private/hostname.domain.name.key
    certs_by_serial/01.pem
  3. Removed all lines from index.txt except 1st (server's cert): V 261015175821Z 01 unknown /CN=hostname.domain.name
  4. Wrote to file serial value 01 - serial of server's cert.
  5. Did gen-req for test user.
  6. Tried sign-req with easyrsa 3.2.1 and got the same error.
  7. Then sign-req with easyrsa 3.1.7 without errors.

From new pki certs_by_serial/28611EEA07314774819525416692C028.pem have lines:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            28:61:1e:ea:07:31:47:74:81:95:25:41:66:92:c0:28

From old pki certs_by_serial/01.pem (server's cert) have lines:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)

Maybe it looks at Serial Number, but doesn't understand the old format and starts looking at Subject?

mandree commented 1 week ago

I don't care as long as you don't show me a way to reproduce the bug. If your previous comment convinces the easy-rsa authors, we'll see a fix in the next official release and take it to FreeBSD from there. Until then, I'll unsubscribe from this bug.

TinCanTech commented 1 week ago

@VVD note in your logs there is this error report (3rd line) above what you try to fix.

The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'hostname.domain.name'
ERROR:There is already a certificate for /CN=hostname.domain.name

@mandree This appears to be the root of the problem.

@VVD Please confirm that the file: pki/index.txt.attr contains the following:

unique_subject = no
TinCanTech commented 1 week ago

Considering the upgrade path from v3.0.8 to v3.2.0, it is possible that the file pki/index.txt.attr has not been upgraded to include unique_subject = no.

This is also addressed by the file openssl-easyrsa.cnf.

@VVD This most likely indicates that you have customised your openssl-easyrsa.cnf file.

EasyRSA cannot be responsible for user changes of the SSL config file.

TinCanTech commented 1 week ago

@VVD Please share the SHA256 hash of your current openssl-easyrsa.cnf file.

VVD commented 1 week ago

@VVD Please confirm that the file: pki/index.txt.attr contains the following:

unique_subject = no

Considering the upgrade path from v3.0.8 to v3.2.0, it is possible that the file pki/index.txt.attr has not been upgraded to include unique_subject = no.

I have:

unique_subject = yes

Probably it was default for easyrsa 3.0.x.

This is also addressed by the file openssl-easyrsa.cnf.

@VVD This most likely indicates that you have customised your openssl-easyrsa.cnf file.

EasyRSA cannot be responsible for user changes of the SSL config file.

@VVD Please share the SHA256 hash of your current openssl-easyrsa.cnf file.

openssl-easyrsa.cnf is from ~3.0.7 too. 2494e39d7d7d2af8af19927d4119d147def593de2d365713a16d946d68bb64b0

Equal to this: https://github.com/OpenVPN/easy-rsa/blob/4ce6e9c8e4b681c739b179a506a8ad1ca6d6ebe4/easyrsa3/openssl-easyrsa.cnf

VVD commented 1 week ago

Updating openssl-easyrsa.cnf and replacing unique_subject = yes with unique_subject = no in pki/index.txt.attr did not fix EASYRSA_REQ_CN.

TinCanTech commented 1 week ago

@VVD Thanks for sharing.

Your initial settings would obviously prohibit duplicate commonName, as set by --req-cn.

As for your updated settings, please provide the easyrsa output from the failure.

VVD commented 1 week ago

As for your updated settings, please provide the easyrsa output from the failure.

@TinCanTech, after updating no failures, but all new records in pki/index.txt have same CN /CN=hostname.domain.name and Subject: CN=hostname.domain.name in *.crt (pki/vars have line set_var EASYRSA_REQ_CN "hostname.domain.name").

TinCanTech commented 1 week ago

after updating no failures

Good.

but all new records in pki/index.txt have same CN /CN=hostname.domain.name and Subject: CN=hostname.domain.name in *.crt (pki/vars have line set_var EASYRSA_REQ_CN "hostname.domain.name")

That is the expected behavior.

Remove set_var EASYRSA_REQ_CN "hostname.domain.name" from your vars file.

VVD commented 1 week ago

That is the expected behavior.

Remove set_var EASYRSA_REQ_CN "hostname.domain.name" from your vars file.

I know. And this code is the cause:

       if [ "$EASYRSA_REQ_CN" = ChangeMe ]; then
                export EASYRSA_REQ_CN="$file_name_base"
       fi

Can you please explain why this if is here?

TinCanTech commented 1 week ago

The default setting for EASYRSA_REQ_CN is ChangeMe.

If this default has not been changed then the commonName is set to file_name_base.

If you have previously set EASYRSA_REQ_CN, via --req-cn or the vars file, then your setting remains as the request commonName.

This is expected behavior and also the reason why EASYRSA_REQ_CN is not a suitable variable to set in the vars file.

VVD commented 1 week ago

The default setting for EASYRSA_REQ_CN is ChangeMe.

If this default has not been changed then the commonName is set to file_name_base.

If you have previously set EASYRSA_REQ_CN, via --req-cn or the vars file, then your setting remains as the request commonName.

This is expected behavior and also the reason why EASYRSA_REQ_CN is not a suitable variable to set in the vars file.

This is clear from the code (I know shell). I asked why it is done this way in the code? Why you added if [ "$EASYRSA_REQ_CN" = ChangeMe ]; then? This line changed the old behavior. Why is the new behavior right and why was the old behavior wrong?

TinCanTech commented 1 week ago

I asked why it is done this way in the code?

Because that is the correct way.

This line changed the old behavior

Why is the new behavior right and why was the old behavior wrong?

Allowing duplicate commonName allows certificate renewal.

TinCanTech commented 6 days ago

@VVD

openssl-easyrsa.cnf is from ~3.0.7 too. 2494e39d7d7d2af8af19927d4119d147def593de2d365713a16d946d68bb64b0

Equal to this: https://github.com/OpenVPN/easy-rsa/blob/4ce6e9c8e4b681c739b179a506a8ad1ca6d6ebe4/easyrsa3/openssl-easyrsa.cnf

Your file may be similar to the file you linked to but it is not the same.

For that file, the hash is 5aa45591602d81f7851a1d39bde72d56a20e5eca8ccbf930867eade176cba6b4

I do not think it is necessary to add this hash to easyrsa: write_easyrsa_ssl_cnf_tmp().

I am also satisfied that any behavioral changes are positive improvements.

~A minor imprvement: There could be a warning or confirmation when using --req-cn/EASYRSA_REQ_CN without --batch.~

VVD commented 6 days ago

@VVD

openssl-easyrsa.cnf is from ~3.0.7 too. 2494e39d7d7d2af8af19927d4119d147def593de2d365713a16d946d68bb64b0 Equal to this: https://github.com/OpenVPN/easy-rsa/blob/4ce6e9c8e4b681c739b179a506a8ad1ca6d6ebe4/easyrsa3/openssl-easyrsa.cnf

Your file may be similar to the file you linked to but it is not the same.

For that file, the hash is 5aa45591602d81f7851a1d39bde72d56a20e5eca8ccbf930867eade176cba6b4

$ wget https://github.com/OpenVPN/easy-rsa/raw/4ce6e9c8e4b681c739b179a506a8ad1ca6d6ebe4/easyrsa3/openssl-easyrsa.cnf
--2024-09-30 00:43:49--  https://github.com/OpenVPN/easy-rsa/raw/4ce6e9c8e4b681c739b179a506a8ad1ca6d6ebe4/easyrsa3/openssl-easyrsa.cnf
Resolving github.com (github.com)... 140.82.121.3
Connecting to github.com (github.com)|140.82.121.3|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://raw.githubusercontent.com/OpenVPN/easy-rsa/4ce6e9c8e4b681c739b179a506a8ad1ca6d6ebe4/easyrsa3/openssl-easyrsa.cnf [following]
--2024-09-30 00:43:49--  https://raw.githubusercontent.com/OpenVPN/easy-rsa/4ce6e9c8e4b681c739b179a506a8ad1ca6d6ebe4/easyrsa3/openssl-easyrsa.cnf
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 2606:50c0:8000::154, 2606:50c0:8003::154, 2606:50c0:8002::154, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|2606:50c0:8000::154|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4616 (4.5K) [text/plain]
Saving to: 'openssl-easyrsa.cnf'

openssl-easyrsa.cnf             100%[=======================================================>]   4.51K  --.-KB/s    in 0.001s

2024-09-30 00:43:49 (4.53 MB/s) - 'openssl-easyrsa.cnf' saved [4616/4616]

$ sha256 openssl-easyrsa.cnf
SHA256 (openssl-easyrsa.cnf) = 2494e39d7d7d2af8af19927d4119d147def593de2d365713a16d946d68bb64b0

I do not think it is necessary to add this hash to easyrsa: write_easyrsa_ssl_cnf_tmp().

I don't understand what you mean.

TinCanTech commented 6 days ago

Hash: 5aa45591602d81f7851a1d39bde72d56a20e5eca8ccbf930867eade176cba6b4

# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always,issuer:always

Hash: 2494e39d7d7d2af8af19927d4119d147def593de2d365713a16d946d68bb64b0

# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always,issuer:always<newLine>

Missing new line due to copy/paste error. Now fixed.