Ten problem jest specyficzny dla MinGW / MSYS, który jest powszechnie używany jako część pakietu Git for Windows .
Rozwiązaniem jest przekazanie -subj
argumentu z początkiem //
(podwójne ukośniki w przód), a następnie użycie \
(ukośnika odwrotnego) do oddzielenia par klucz / wartość. Lubię to:
"//O=Org\CN=Name"
Zostanie to następnie magicznie przekazane openssl
w oczekiwanej formie:
"/O=Org/CN=Name"
Aby odpowiedzieć na konkretne pytanie, należy zmienić -subj
wiersz w skrypcie na następujący.
-subj "//C=GB\ST=someplace\L=Provo\O=Achme\CN=${FQDN}"
To powinno wystarczyć.
Co to za magia?
Dla ciekawych tego, co się tutaj dzieje, mogę wyjaśnić tę tajemnicę. Powodem jest to, że MSYS rozsądnie zakłada, że argumenty zawierające ukośniki są w rzeczywistości ścieżkami. A kiedy te argumenty są przekazywane do pliku wykonywalnego, który nie został skompilowany specjalnie dla MSYS (tak jak openssl
w tym przypadku), wówczas konwertuje on ścieżki POSIX na ścieżki Win32 . Zasady tej konwersji są dość złożone, ponieważ MSYS stara się jak najlepiej uwzględniać większość typowych scenariuszy współdziałania. To wyjaśnia również, dlaczego używanie openssl
z wiersza poleceń systemu Windows ( cmd.exe
) działa dobrze, ponieważ nie są wykonywane żadne magiczne konwersje.
Możesz przetestować konwersję w ten sposób.
$ cmd //c echo "/CN=Name"
"C:/Program Files (x86)/Git/CN=Name"
Nie możemy użyć echo
pliku wykonywalnego, który jest dostarczany z MSYS, ponieważ został skompilowany dla MSYS, zamiast tego użyjemy echo
wbudowanego cmd
. Zauważ, że ponieważ cmd
przełączniki zaczynają się od /
(typowe dla poleceń systemu Windows), musimy obsługiwać to za pomocą podwójnych ukośników. Jak widać na wyjściu, argument został rozszerzony do ścieżki systemu Windows i staje się jasne, dlaczego openssl
rzeczywiście tak twierdzi Subject does not start with '/'.
.
Zobaczmy więcej konwersji.
$ cmd //c echo "//CN=Name"
/CN=Name
Podwójne ukośniki sprawiają, że MSYS uważa, że argument jest przełącznikiem stylu systemu Windows, który powoduje usunięcie /
tylko (bez konwersji ścieżki). Można by pomyśleć, że dzięki temu moglibyśmy po prostu użyć ukośników, aby dodać więcej par klucz / wartość. Spróbujmy tego.
$ cmd //c echo "//O=Org/CN=Name"
//O=Org/CN=Name
Nagle podwójne cięcia na początku nie są usuwane. Dzieje się tak, ponieważ teraz, z ukośnikiem po początkowych podwójnych ukośnikach, MSYS uważa, że odwołujemy się do ścieżki UNC (np. // serwer / ścieżka). Gdyby to zostało przekazane do openssl
tego, pomijałoby pierwszy klucz / wartość mówiącą Subject Attribute /O has no known NID, skipped
.
Oto odpowiednia reguła z wiki MinGW wyjaśniająca to zachowanie:
- Argument zaczynający się od 2 lub więcej / jest uważany za przełącznik stylu Windows ze znakami ucieczki i zostanie przekazany z początkiem / usuniętym, a wszystkie \ zmienione na /.
- Z wyjątkiem tego, że jeśli występuje / po wiodącym bloku /, argument jest uważany za ścieżkę UNC, a wiodący / nie jest usuwany.
W tej regule widzimy metodę, której moglibyśmy użyć do stworzenia żądanego argumentu. Ponieważ wszystko, \
co następuje w argumencie zaczynającym się od, //
zostanie przekonwertowane na zwykły /
. Wypróbujmy to.
$ cmd //c echo "//O=Org\CN=Name"
/O=Org/CN=Name
I jak widzimy, to działa.
Mam nadzieję, że to trochę demistyfikuje magię.
cat -vet /path/to/script
i zobacz, czy wiersze kończą się na „^ M $” (w stylu Windows), czy po prostu na „$” (w stylu unix).