此问题特定于MinGW / MSYS,后者通常用作Windows 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
在Windows命令提示符(cmd.exe
)中使用效果很好,因为没有进行神奇的转换。
您可以像这样测试转换。
$ cmd //c echo "/CN=Name"
"C:/Program Files (x86)/Git/CN=Name"
由于echo
MSYS随附的可执行文件是为MSYS编译的,因此我们无法使用它,而是使用echo
内置的cmd
。请注意,由于cmd
开关以/
(对于Windows命令常见)开头,因此我们需要使用双斜杠来处理。正如我们在输出中看到的那样,该参数已扩展到Windows路径,并且很清楚为什么openssl
确实声明了它Subject does not start with '/'.
。
让我们看看更多的转换。
$ cmd //c echo "//CN=Name"
/CN=Name
双斜杠使MSYS认为该参数是Windows样式的开关,导致/
仅剥离(无路径转换)。您可能会认为,我们可以仅使用斜杠添加更多键/值对。让我们尝试一下。
$ cmd //c echo "//O=Org/CN=Name"
//O=Org/CN=Name
突然,开始时的双斜杠没有被删除。这是因为现在,在最初的双斜杠之后有一个斜杠,MSYS认为我们正在引用UNC路径(例如// server / path)。如果将其传递给openssl
它,则会跳过第一个键/值“” Subject Attribute /O has no known NID, skipped
。
这是MinGW Wiki中解释此行为的相关规则:
- 以2或更大的/开头的参数被认为是Windows样式的转义参数,并将以前导/删除且所有\更改为/传递。
- 除非在/的前导块之后有一个/,否则该参数被视为UNC路径,并且不删除前导/。
在此规则中,我们可以看到可用于创建所需参数的方法。由于\
以参数开头的所有后续内容//
都将转换为plain /
。让我们尝试一下。
$ cmd //c echo "//O=Org\CN=Name"
/O=Org/CN=Name
正如我们所见,它确实有效。
希望这能使魔术变得神秘。
cat -vet /path/to/script
,然后查看行是否以'^ M $'(Windows风格)或仅以'$'(unix风格)结尾。