J'écris un script bash qui utilisera openssl pour générer une demande de signature de certificat avec conforme à l'extension X509v3 nom alternatif.
Comme il n'y a pas d'option de ligne de commande pour cela, une solution a été d'utiliser l'option -config
conjointement avec l'option -reqexts
en ajoutant les valeurs SAN au fichier de configuration par défaut.
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
Mon problème est la portabilité. Bien que une question similaire m'assure que cela fonctionne dans mon environnement Ubuntu car le fichier de configuration par défaut est /etc/ssl/openssl.cnf
, malheureusement, cela ne fonctionnera pas partout, Windows étant l'exemple le plus évident.
Comment je par programme détermine-t-il le chemin complet du fichier openssl default fichier de configuration?
Il y a un indice flagrant dans la documentation
-config nomfichier
Ceci permet de spécifier un autre fichier de configuration, il remplace le nom de fichier de la compilation ou tout autre élément spécifié dans la variable d'environnement OPENSSL_CONF.
J'ai lu la documentation config et recherché le code source , mais je ne peux pas découvrir le mécanisme par lequel il choisit l'endroit où charger le fichier de configuration par défaut "compile time". Si je pouvais le trouver, je préférerais alors le charger en tant que variable dans le script plutôt que le chemin codé en dur.
De plus, ma variable $OPENSSL_CONF
est vide.
Actuellement, mon script vérifie ces conditions et utilise le premier qui est évalué à true:
$OPENSSL_CONF
est renseignée et le fichier existe/etc/ssl/openssl.cnf
existeSi aucune de celles-ci n'est vraie, cela inclut une copie d'une configuration standard. Cela n'est pas souhaitable car cela aurait pour effet de remplacer les paramètres personnalisés établis par le client. Je souhaite utiliser complètement les conditions de l'environnement et ajouter simplement la section SAN en tant qu'addenda.
Je pourrais encore étendre cette chaîne avec les chemins des suspects habituels ou même une recherche de système. Mais dans le cas où plusieurs existent, je n’ai aucune garantie quant à ce qui est en fait utilisé par openssl par défaut.
Comment déterminer par programme le chemin d'accès complet au fichier de configuration par défaut openssl?
Par programme, c’est aussi simple que d’utiliser la macro OPENSSLDIR
de 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"
Comment déterminer l'emplacement par défaut de openssl.cnf?
Voici plus d'informations pour vous aider à combler les lacunes de l'autre question sur le dépassement de capacité. Cela dépend de l'installation OpenSSL que vous utilisez.
Voici la réponse courte ... La bibliothèque et les programmes recherchent openssl.cnf
dans OPENSSLDIR
. OPENSSLDIR
est une option de configuration et est définie avec --openssldir
.
Je suis sur un MacBook avec 3 OpenSSL différents (Apple, MacPort et celui que je construis):
# 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"
Voici la réponse la plus longue ... C'est un peu enfoui dans le code source OpenSSL pour apps.c
, load_config
et ce qui se produit lorsque cnf
est NULL
(c'est-à-dire, aucune option -config
ou OPENSSL_CONF
envar). Lorsque cnf
est NULL
et qu'il n'y a pas de substitution, alors OPENSSLDIR
est utilisé.
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;
}
... cela fonctionne dans mon environnement Ubuntu car le fichier de configuration par défaut est
/etc/ssl/openssl.cnf
; malheureusement, cela ne fonctionnera pas partout, Windows étant l'exemple le plus évident.
Cela peut toujours être un problème pour vous sous Windows. Vous devriez être OK si vous construisez OpenSSL à partir de sources vous-même; modulo leur gestion de nom de fichier long sous Windows (voir aussi Problème n ° 4490: "Installation de nmake" échoue "La destination doit être un répertoire situé à.\util\copy.pl ligne 39" sur ).
Des personnes comme Shinning Light et Win32 OpenSSL fournissent les programmes d'installation et OpenSSL ne peuvent pas être installées dans le répertoire que le gestionnaire de paquets a envisagé. J'ai même vu des répertoires Unix tels que /usr/local
apparaître sur des machines Windows.
Pour Windows, votre pari le plus sûr est probablement de définir la variable d'environnement OPENSSL_CONF
pour remplacer les chemins d'accès brisés et les bogues de traitement des chemins.
De plus, je ne suis pas au courant d'un appel d'API CONF_*
ou NCONF_*
qui vous donne le répertoire effectif au moment de l'exécution. Ici, le répertoire effectif serait le répertoire de configuration plus des choses telles que OPENSSL_CONF
remplace. Ouvrez maintenant dans la liste des utilisateurs OpenSSL: Obtenir le chemin OPENSSLDIR effectif à l'exécution?
Comme mentionné dans l'un des commentaires, la réponse simple devrait être de trouver le chemin à l'aide de la commande suivante:
openssl version -d
Si cela ne fonctionne pas, vous pouvez présumer qu'OpenSSL n'est pas configuré correctement ou du moins n'a pas la configuration dont vous avez besoin. Voici un exemple dans Node.js sur la façon dont vous pouvez obtenir l'emplacement de 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);
})();