खिड़कियों पर एक बैश स्क्रिप्ट से Openssl चलाना - विषय '/' से शुरू नहीं होता है


83

मेरी स्क्रिप्ट में मेरे पास है:

openssl req \
  -x509 \
  -new \
  -nodes \
  -key certs/ca/my-root-ca.key.pem \
  -days 3652 \
  -out certs/ca/my-root-ca.crt.pem \
  -subj "/C=GB/ST=someplace/L=Provo/O=Achme/CN=${FQDN}"

Git Bash 3.1 में विंडोज पर इसे चलाना देता है:

Subject does not start with '/'.

उप की तरह भागने की कोशिश की: -subj \ "/ C = UK / ST = कहीं न कहीं / L = Provo / O = Achme / CN = $ {FQDN} \"

फिर भी काम नहीं करता है। कोई विचार?


1
पहला पहला प्रश्न: क्या आपकी स्क्रिप्ट फ़ाइल में DOS / Windows- शैली की लाइन एंडिंग्स (कैरिज रिटर्न + लाइनफीड), या यूनिक्स-शैली (सिर्फ लाइनफीड) है? स्क्रिप्ट को प्रिंट करने का प्रयास करें cat -vet /path/to/script, और देखें कि क्या लाइनें '^ M $' (विंडोज़-शैली) या सिर्फ '$' (यूनिक्स-शैली) के साथ समाप्त होती हैं।
गॉर्डन डेविसन

1
यह बैश स्क्रिप्ट है? किस माहौल में चलें? set -vxइस लाइन के लिए स्क्रिप्ट शो के शीर्ष में क्या जोड़ा जा रहा है?
इटन रीसनर

@EtanReisner set -vxउपयोगी है धन्यवाद! पर्यावरण विंडोज है, जीआईटी बैश 3.1। -Vx के साथ , मुझे वह मिलता है + openssl req -x509 -new -nodes -key certs/ca/my-root-ca.key.pem -days 3652 -out certs/ca/my-root-ca.crt.pem -subj /C=GB/ST=someplace/L=Provo/O=Achme/CN=domain.comजो अन-कोटेड -subjस्ट्रिंग दिखाता है । लेकिन मैं इसे स्क्रिप्ट से उद्धृत रूप में प्राप्त करने के लिए काम नहीं कर सकता।
is4242

@GordonDavisson धन्यवाद! स्क्रिप्ट में '^ M $' लाइन एंडिंग है
iss42

1
-vxआउटपुट में एक निर्विवाद तर्क आश्चर्यजनक या एक समस्या नहीं है। उद्धरण कमांड निष्पादन के लिए नहीं बल्कि शेल पार्सिंग के लिए हैं। वह आउटपुट मुझे सही लगता है। DOS लाइन एंडिंग आम तौर पर एक अच्छा विचार नहीं है, लेकिन यहाँ कोई समस्या उत्पन्न नहीं हुई है (जब तक कि उन्हें हटाने से यह समस्या ठीक नहीं होती है जिस स्थिति में मैं त्रुटि संदेश से थोड़ा भ्रमित हूं)।
इटन रीसनर

जवाबों:


197

यह समस्या MinGW / MSYS के लिए विशिष्ट है जो आमतौर पर विंडोज पैकेज के लिए Git के हिस्से के रूप में उपयोग की जाती है ।

इसका समाधान -subjअग्रणी //(डबल फ़ॉरवर्ड स्लैश) के साथ तर्क को पास करना है और फिर \कुंजी / मूल्य जोड़े को अलग करने के लिए (बैकस्लैश) का उपयोग करना है। ऐशे ही:

"//O=Org\CN=Name"

यह तब opensslअपेक्षित रूप में जादुई रूप से पारित हो जाएगा :

"/O=Org/CN=Name"

तो विशिष्ट प्रश्न का उत्तर देने के लिए, आपको -subjअपनी स्क्रिप्ट में निम्नलिखित के लिए लाइन बदलनी चाहिए ।

-subj "//C=GB\ST=someplace\L=Provo\O=Achme\CN=${FQDN}"

आपको बस इतना ही चाहिए।

यह कैसा जादू है?

उन लोगों के बारे में जानने के लिए जो यहां चल रहे हैं, मैं इस रहस्य को समझा सकता हूं। कारण यह है कि MSYS यथोचित मानता है कि स्लैश वाले तर्क वास्तव में पथ हैं। और जब उन तर्कों को एक निष्पादन योग्य के लिए पारित किया जाता है जिन्हें विशेष रूप से MSYS (जैसे opensslइस मामले में) के लिए संकलित नहीं किया गया है, तो यह POSIX पथ को Win32 पथ में बदल देगा । इस रूपांतरण के नियम काफी जटिल हैं क्योंकि MSYS इंटरऑपरेबिलिटी के लिए सबसे आम परिदृश्यों को कवर करने की पूरी कोशिश करता है। यह भी बताता है कि opensslविंडोज़ कमांड प्रॉम्प्ट ( cmd.exe) से उपयोग करना ठीक काम करता है, क्योंकि कोई जादुई रूपांतरण नहीं किया जाता है।

आप इस तरह रूपांतरण का परीक्षण कर सकते हैं।

$ cmd //c echo "/CN=Name"
"C:/Program Files (x86)/Git/CN=Name"

हम echoMSYS के साथ आने वाले निष्पादन योग्य का उपयोग नहीं कर सकते हैं क्योंकि यह MSYS के लिए संकलित किया गया था, इसके बजाय हम echoअंतर्निहित का उपयोग करेंगे cmd। ध्यान दें कि चूंकि cmdस्विचेस /(विंडोज़ कमांड्स के लिए आम) के साथ शुरू होता है, इसलिए हमें इसे डबल स्लैश के साथ संभालना होगा। जैसा कि हम आउटपुट में देख सकते हैं कि तर्क को विंडोज़ पथ में विस्तारित किया गया था और यह स्पष्ट हो जाता है कि opensslवास्तव में यह दावा क्यों करता है Subject does not start with '/'.

आइए देखते हैं कुछ और रूपांतरण।

$ cmd //c echo "//CN=Name"
/CN=Name

डबल स्लैश बनाता है MSYS का मानना ​​है कि तर्क एक विंडोज़ शैली स्विच है जिसके परिणामस्वरूप /केवल (कोई पथ रूपांतरण नहीं) होता है। आपको लगता है कि इसके साथ हम स्लैश का उपयोग अधिक महत्वपूर्ण / मूल्य जोड़े को जोड़ने के लिए कर सकते हैं। चलो कोशिश करते हैं कि।

$ cmd //c echo "//O=Org/CN=Name"
//O=Org/CN=Name

अचानक शुरू में डबल स्लैश को कम नहीं किया गया है। ऐसा इसलिए है क्योंकि अब, शुरुआती डबल स्लैश के बाद एक स्लैश के साथ, MSYS को लगता है कि हम एक UNC पथ (जैसे // सर्वर / पथ) का संदर्भ दे रहे हैं। यदि यह इसके लिए पारित किया गया था opensslतो पहली कुंजी / मान को छोड़ देगा Subject Attribute /O has no known NID, skipped

इस व्यवहार की व्याख्या करने वाले MinGW विकि से प्रासंगिक नियम इस प्रकार है:

  • 2 या अधिक / के साथ शुरू होने वाले तर्क को एक बची हुई विंडोज शैली स्विच माना जाता है और इसे प्रमुख / हटाए गए और सभी \ / में बदल दिया जाएगा।
    • सिवाय इसके कि अगर / के अग्रणी ब्लॉक / के बाद कोई तर्क UNC पथ माना जाता है और प्रमुख / हटाया नहीं जाता है।

इस नियम में हम उस विधि को देख सकते हैं जिसका उपयोग हम अपने इच्छित तर्क को बनाने के लिए कर सकते हैं। चूँकि \शुरू होने वाले तर्क में सभी //को सादे में बदल दिया जाएगा /। चलो कोशिश करते हैं कि बाहर।

$ cmd //c echo "//O=Org\CN=Name"
/O=Org/CN=Name

और जैसा कि हम देख सकते हैं कि यह काम करता है।

आशा है कि यह जादू को थोड़ा कम करेगा।


1
महान व्याख्या।
ट्रेबोर

4
क्या होगा अगर मैं bashलिनक्स पर्यावरण में चाबियाँ उत्पन्न करने के लिए उसी -स्क्रिप्ट का उपयोग करता हूं ? यह कैसे समझा जाएगा कि लाइन के बीच में डबल स्लैश और बैकस्लैश?
टोमिलोव अनातोली

3
@ ऑरिजिनल लिनक्स को दूसरी दिशा में स्लैश की आवश्यकता होती है, इसलिए आपको यह पता लगाना होगा कि यह किस प्रकार की प्रणाली पर चल रहा है - यहां एक उत्तर दिया गया है जो एक caseस्टेटमेंट का उपयोग करता है और uname -sपर्यावरण का पता लगाने के लिए, जिसे आप ifउपयुक्त उपयोग करने के लिए उपयोग कर सकते हैं स्लैश - stackoverflow.com/questions/3466166/...
टिम लुईस

अत्यन्त अद्भुत। मैं एक ही मुद्दे के साथ पकड़ा गया और पूरी तरह से POSIX के बारे में Win32 पथ रूपांतरण के लिए भूल गया था। यह सोचते हुए कि मैं इसे गलत बता रहा हूं।
davewasthere

0

मैंने व्यक्तिगत रूप से इसे ओपनएसएसएल बाइनरी के उपयोग के लिए विशिष्ट पाया। Msys2 / mingw64 का उपयोग करते हुए मेरे सिस्टम पर मैंने देखा है कि दो अलग-अलग OpenSSL बायनेरिज़ मौजूद हैं, उदाहरण के लिए:

$ whereis openssl; echo; which openssl
openssl: /usr/bin/openssl.exe /usr/lib/openssl /mingw64/bin/openssl.exe /usr/share/man/man1/openssl.1ssl.gz

/mingw64/bin/openssl

मेरा मानना ​​है कि इसका उपयोग /mingw64/bin/opensslउस विषय का उपयोग करने की आवश्यकता है //, जिसके साथ शुरू होता है , हालांकि मुझे यकीन नहीं है कि यह पैकेज / बिल्ड या ओपनएसएसएल के संस्करण के लिए विशिष्ट है ताकि यह सुनिश्चित हो सके कि प्रत्येक बाइनरी का संस्करण नीचे है:

$ while read -r _openSslBin; do printf "${_openSslBin}: "; ${_openSslBin} version; done < <(whereis openssl | egrep -o '[^ ]+?\.exe ')
/usr/bin/openssl.exe: OpenSSL 1.0.2p  14 Aug 2018
/mingw64/bin/openssl.exe: OpenSSL 1.1.1  11 Sep 2018

मैं अपने मशीन पर काम करने के लिए msys / mingw का उपयोग करते समय OpenSSL संस्करण के आधार पर सही बाइनरी का चयन करने के लिए bash कोड का निम्न उदाहरण पाया है:

# determine openssl binary to use based on OS
# -------------------------------------------
_os="$(uname -s | awk 'BEGIN{FS="_"} {print $1}' | egrep -o '[A-Za-z]+')"
if [ "${_os,,}" = "mingw" ] || [ "${_os,,}" == "msys" ]; then
  while read -r _currentOpenSslBin; do
    if [[ "$(${_currentOpenSslBin}  version | awk '{print $2}')" =~ ^(1\.0\.[0-9].*|0\.\9\.8.*)$ ]]; then
      _openSslBin="${_currentOpenSslBin}"
    fi
  done < <(whereis openssl | egrep -o '\/[^ ]+?\.exe ' | egrep -v 'mingw')
  if [ -n "${_openSslBin}" ]; then
    printf "OpenSSL Binary: ${_openSslBin} (v. $(${_openSslBin}  version | awk '{print $2}'))\n"
  else
    printf "Unable to find compatible version of OpenSSL for use with '${_os}' OS, now exiting...\n"
    exit 1
  fi
else
  _openSslBin="openssl"
fi

# display selected openssl binary and it's version
# ------------------------------------------------
printf "${_openSslBin}: "; ${_openSslBin} version

विषय स्ट्रिंग को पास करने के साथ मुद्दों को ठीक करने के अलावा, मुझे यह डीएन के आकार के साथ मुद्दों को हल करने के लिए भी मिला (मैंने एक नीति के साथ एक कस्टम Opensl.cnf पारित किया है जिसने किसी भी फ़ील्ड के लिए max_size सेट नहीं किया था और जो अभी भी समस्या थी का उपयोग करते समय /mingw64/bin/openssl.exe)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.