Git Bash - 开头带有"/"的字符串参数正在扩展到文件路径。如何阻止这种情况?



今天早些时候,我试图用SubjectAltName扩展中的DNSName条目生成一个证书:

$ openssl req -new -subj "/C=GB/CN=foo" -addext "subjectAltName = DNS:foo.co.uk" 
-addext "certificatePolicies = 1.2.3.4" -key ./private-key.pem -out ~/req.pem

此命令导致以下错误消息:

名称的格式应为/type0=value0/type1=value1/type2=。。。其中字符可以被转义。此名称的格式不是:"C:\Program Files/Git/C=GB/CN=foo"制作证书请求时出现问题

如何阻止Git Bash将此字符串参数视为文件路径,或者至少阻止它进行此更改?

Git Bash 2.21.0更新的发布说明今天提到这是一个已知问题。幸运的是,他们还描述了两种解决问题的方法:

如果您指定以斜杠开头的命令行选项,POSIX到Windows的路径转换将启动,例如"/usr/bin/bash.exe";至";C: \Program Files\Git\usr\bin\bash.exe"。当不希望这样时——例如--上传包=/opt/git/bin/git上传包";或"-L/regex/"——您需要临时设置环境变量MSYS_NO_PATHCONV,如下所示:

MSYS_NO_PATHCONV=1 git blame -L/pathconv/ msys2_path_conv.cc

或者,您可以将第一个斜杠加倍以避免POSIX到Windows的路径转换,例如"//usr/bin/bash.exe";。

但是,如果使用波浪号('~')表示主文件夹,MSYS_NO_PATHCONV=1可能会出现问题:

$ MSYS_NO_PATHCONV=1 openssl req -new -subj "/C=GB/CN=foo" -addext "subjectAltName = DNS:foo.co.uk" -addext "certificatePolicies = 1.2.3.4" -key ./userkeys/user_device_priv.pem -out ~/req.pem
Can't open /c/Users/AJM/req.pem for writing, No such file or directory
24780:error:02001003:system library:fopen:No such process:../openssl-1.1.1u/crypto/bio/bss_file.c:69:fopen('/c/Users/AJM/req.pem','w')
24780:error:2006D080:BIO routines:BIO_new_file:no such file:../openssl-1.1.1u/crypto/bio/bss_file.c:76:

在与@quetzalcoatl讨论我最初的问题时,建议使用MSYS2_ARG_CONV_EXCL="*"作为MSYS_NO_PATHCONV=1的替代方案。我已经测试过了,可以确认它也同样有效,但不幸的是,~字符也有同样的问题。

使用的信息

  • https://www.msys2.org/wiki/Porting/
  • https://www.msys2.org/docs/filesystem-paths/#automatic-unix windows路径转换

我们可以实现更细粒度的控制,并消除~的问题。然而,这是以必须手动识别所有各种";看起来像Unix路径而不是":

$ MSYS2_ARG_CONV_EXCL='/C' openssl req -new -subj "/C=GB/CN=foo" -addext "subjectAltName = DNS:foo.co.uk" -addext "certificatePolicies = 1.2.3.4" -key ./userkeys/user_device_priv.pem -out ~/req.pem
# Works OK
$ MSYS2_ARG_CONV_EXCL='/CN' openssl req -new -subj "/CN=foo" -addext "subjectAltName = DNS:foo.co.uk" -addext "certificatePolicies = 1.2.3.4" -key ./userkeys/user_device_priv.pem -out ~/req.pem
# Also works OK.

如果脚本访问文件,使用MSYS_NO_PATHCONV=1可能会有问题。

使用双正斜杠前缀不适用于OpenSSL的特定情况,因为它会导致第一个DN段密钥被读取为"/C"而不是"C",因此OpenSSL将其删除,输出:

req: Skipping unknown attribute "/C"

相反,我使用了一个函数来检测是否在bash for Windows上运行,如果是,则使用"伪"段作为前缀:

# If running on bash for Windows, any argument starting with a forward slash is automatically
# interpreted as a drive path. To stop that, you can prefix with 2 forward slashes instead
# of 1 - but in the specific case of openssl, that causes the first CN segment key to be read as
# "/O" instead of "O", and is skipped. We work around that by prefixing with a spurious segment,
# which will be skipped by openssl
function fixup_cn_subject() {
local result="${1}"
case $OSTYPE in
msys|win32) result="//XX=x${result}"
esac
echo "$result"
}
# Usage example
MY_SUBJECT=$(fixup_cn_subject "/C=GB/CN=foo")

通过传递一个伪值作为第一个属性找到了一个解决方法,例如:-subj '//SKIP=skip/C=gb/CN=foo'

我在使用bash时遇到了同样的问题,但在Powershell中运行完全相同的命令对我来说很有效。希望这能帮助到一些人。

相关内容

最新更新