it-swarm.com.de

Wie kann ich den Standardspeicherort für openssl.cnf ermitteln?

Hintergrund

Ich schreibe ein Bash-Skript, das openssl verwendet, um eine Zertifikatsignierungsanforderung mit X509v3-Erweiterungs-konformzu generieren.

Da es hierfür keine Befehlszeilenoption gibt, war eine Lösung , die Option -config zusammen mit der Option -reqexts zu verwenden, indem die Werte für SAN an die Standardkonfigurationsdatei angefügt werden.

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

Frage

Mein Problem ist die Portabilität. Während eine ähnliche Frage versichert, dass dies in meiner Ubuntu-Umgebung funktioniert, da die Standardkonfigurationsdatei /etc/ssl/openssl.cnf ist, funktioniert dies leider nicht überall, wobei Windows das offensichtliche Beispiel ist.

Wie bestimme ich programmatisch den vollständigen Pfad zur openssl default -Konfigurationsdatei?

Was ich versucht habe

Es gibt einen krassen Hinweis in der Dokumentation

-config Dateiname
Dadurch kann eine alternative Konfigurationsdatei angegeben werden, die die Kompilierzeit Dateiname oder eine andere in der Umgebungsvariable OPENSSL_CONF angegebene überschreibt.

Ich habe die Dokumentation config gelesen und den Quellcode durchsucht, aber ich kann nicht herausfinden, durch welchen Mechanismus sie die Standard-Konfigurationsdatei "compile time" lädt. Wenn ich das finden könnte, würde ich es vorziehen, es statt des hart codierten Pfads als Variable in das Skript zu laden.

Außerdem ist meine $OPENSSL_CONF-Variable leer.

Eine schlechte Alternative

Derzeit überprüft mein Skript diese Bedingungen und verwendet die erste, die als wahr ausgewertet wird:

  1. Die Variable $OPENSSL_CONF ist ausgefüllt und die Datei ist vorhanden
  2. /etc/ssl/openssl.cnf existiert

Wenn keine der beiden zutreffend ist, enthält es eine Kopie einer Standardkonfiguration. Dies ist unerwünscht, da dadurch die vom Client festgelegten benutzerdefinierten Einstellungen überschrieben werden. Ich möchte die Umgebungsbedingungen vollständig nutzen und den Abschnitt SAN einfach als Nachtrag hinzufügen.

Ich könnte diese Kette um die Pfade der üblichen Verdächtigen oder sogar eine Systemsuche erweitern. Für den Fall, dass mehrere existieren, habe ich keine Sicherheit, welche von openssl tatsächlich als Standard verwendet wird.

9
Jeff Puckett

Wie bestimme ich programmatisch den vollständigen Pfad zur Standardkonfigurationsdatei openssl?

Programmgesteuert ist es so einfach wie das OPENSSLDIR-Makro von 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"

Wie kann ich den Standardspeicherort für openssl.cnf ermitteln?

Hier finden Sie weitere Informationen, mit denen Sie die Lücken der anderen Stack Overflow-Frage ausfüllen können. Dies hängt von der von Ihnen verwendeten OpenSSL-Installation ab.

Hier ist die kurze Antwort ... Die Bibliothek und die Programme suchen nach openssl.cnf in OPENSSLDIR. OPENSSLDIR ist eine configure-Option und wird mit --openssldir festgelegt.

Ich bin auf einem MacBook mit 3 verschiedenen OpenSSLs (Apple, MacPort und dem, das ich baue):

# 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"

Hier ist die längere Antwort ... Es ist eine Art von OpenSSL-Quellcode für apps.c, load_config und was passiert, wenn cnfNULL ist (d. H. Keine -config-Option oder OPENSSL_CONF envar). Wenn cnfNULL ist und keine Überschreibungen vorhanden sind, wird OPENSSLDIR verwendet.

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;
}

Dies funktioniert in meiner Ubuntu-Umgebung, da die Standardkonfigurationsdatei /etc/ssl/openssl.cnf ist. Dies funktioniert leider nicht überall. Windows ist das offensichtliche Beispiel.

Unter Windows ist dies möglicherweise immer noch ein Problem. Sie sollten OK sein, wenn Sie OpenSSL selbst aus Quellen erstellen. modulo ihre Behandlung mit langen Dateinamen in Windows (siehe auch Problem # 4490: "nmake install" schlägt fehl "Ziel muss ein Verzeichnis in.\util\copy.pl Zeile 39" in sein).

Benutzer wie Shinning Light und Win32 OpenSSL stellen Installationsprogramme bereit, und OpenSSL möglicherweise nicht wird in dem Verzeichnis installiert, das vom Packager vorgesehen ist. Ich habe sogar gesehen, dass Unix-Verzeichnisse wie /usr/local auf Windows-Rechnern erscheinen.

Für Windows ist Ihre sicherste Wette wahrscheinlich, dass die Umgebungsvariable OPENSSL_CONF so eingestellt ist, dass gebrochene Pfade und Fehler bei der Pfadverarbeitung überschrieben werden.


Ich kenne auch keinen CONF_*- oder NCONF_*-API-Aufruf, der Ihnen das effektive Verzeichnis zur Laufzeit gibt. Das effektive Verzeichnis wäre hier das Konfigurationsverzeichnis plus Dinge wie OPENSSL_CONF überschreibt. Jetzt in der OpenSSL-Benutzerliste öffnen: Gültigen OPENSSLDIR-Pfad zur Laufzeit abrufen?

6
jww

Wie in einem Kommentar erwähnt, sollte die einfache Antwort darin bestehen, den Pfad mithilfe des folgenden Befehls zu finden:

openssl version -d

Wenn dies nicht funktioniert, können Sie davon ausgehen, dass OpenSSL nicht richtig konfiguriert ist oder zumindest nicht über die erforderliche Konfiguration verfügt. In Node.js finden Sie ein Beispiel, wie Sie den Speicherort von openssl.cnf ermitteln können:

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