36

Earlier today, I was trying to generate a certificate with a DNSName entry in the SubjectAltName extension:

$ 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

This command led to the following error message:

name is expected to be in the format /type0=value0/type1=value1/type2=... where characters may be escaped by . This name is not in that format: 'C:/Program Files/Git/C=GB/CN=foo' problems making Certificate Request

How can I stop Git Bash from treating this string parameter as a filepath, or at least stop it from making this alteration?

AJM
  • 1,317
  • 2
  • 15
  • 30
  • possible duplicate, 8yrs older, with lots of answers (not 100% the same environment, but very close, and it totally looks like the asnwers may be helpful): https://stackoverflow.com/questions/7250130/how-to-stop-mingw-and-msys-from-mangling-path-names-given-at-the-command-line – quetzalcoatl Jul 05 '23 at 08:39
  • 1
    See also [MSYS docs](https://www.msys2.org/docs/filesystem-paths/#automatic-unix-windows-path-conversion) that explain the path conversion, and how to control what gets converted (especially the MSYS2_ARG_CONV_EXCL/MSYS2_ENV_CONV_EXCL for fine-grained control, but it doesn't mention total MSYS_NO_PATHCONV switch, so dear reader in the future - do a bit of research to see if it's compatible to your env) – quetzalcoatl Jul 05 '23 at 08:52
  • @quetzalcoatl `MSYS_NO_PATHCONV` is exclusive to Git Bash, as noted in [this comment](https://stackoverflow.com/questions/7250130/how-to-stop-mingw-and-msys-from-mangling-path-names-given-at-the-command-line#comment57422029_34386471). So it wouldn't be in Cygwin or an msys2 variant. – AJM Jul 07 '23 at 17:39
  • @quetzalcoatl I've also attempted to reproduce the "treating this string parameter as a filepath" problem in msys2 msys, and it wasn't affected. So that question isn't a duplicate and it does need to be the same environment. – AJM Jul 07 '23 at 17:42
  • 1
    That said, I've tested `MSYS2_ARG_CONV_EXCL="*"` in Git Bash, and it solves the problem just as `MSYS_NO_PATHCONV=1` did, so you have found at least one new solution in addition to the ones in my answer below. – AJM Jul 07 '23 at 18:19
  • 1
    Trying to get more fine-grained control from `MSYS2_ARG_CONV_EXCL` doesn't seem to work with command-line arguments of the form `"-argname "` instead of `"--argname="`. All of `MSYS2_ARG_CONV_EXCL="-subj"`, `MSYS2_ARG_CONV_EXCL="-subj "`, `MSYS2_ARG_CONV_EXCL='-subj'` and `MSYS2_ARG_CONV_EXCL='-subj '` failed in the example above. – AJM Jul 07 '23 at 18:33
  • 1
    Ah - [a different page](https://www.msys2.org/wiki/Porting/) in the msys docs explains what to do. In the case of `-subj "/C=GB/CN=foo"` above, `MSYS2_ARG_CONV_EXCL='/C'` gives the finer-grained control needed. For `-subj "CN=foo"` I would use `MSYS2_ARG_CONV_EXCL='/CN'`. This is certainly turning into an educational comment thread. – AJM Jul 07 '23 at 18:40
  • From what I understood, ARG_CONV_EXCL works pretty straightforward and porcelain-agnostic. The 'parameter' they see and consider for matching is the direct entry in argv, and the matching is by prefix. If the commandline contains `--argname=foobar` then it is 1 parameter, and if `--argname foobar` then it is in fact 2 parameters. If I wanted to match the former, I need `..._EXCL="--argname=foobar"`, and to match the latter, I need `..._EXCL="foobar"`. So in case you provided I think it could be `..._EXCL="/C="` and `..._EXCL="CN="` with no `/`, and both with `=` in case some `CNF=` shows up. – quetzalcoatl Jul 07 '23 at 22:39
  • Of course that extra `=` is just a precaution against prefix collisions in this case of directory expression, not really something needed by the MSYS mechanism. Anyways, what I really like about this is that they actually thought about making it a list-of-prefixes, so it can contain multiple needles to be found, and for example `..._EXCL="/C=;CN="` would match both cases. Yay! – quetzalcoatl Jul 07 '23 at 22:43
  • 1
    @quetzalcoatl I'd like to edit this information into my answer below. But due to the moderation strike, I'd also like to delay making the edit until the strike is over. Would this be OK with you? – AJM Jul 10 '23 at 11:54
  • 1
    Also, where you said " If I wanted to match the former, I need `..._EXCL="--argname=foobar`". As far as I can tell, all you need there is `MSYS2_ARG_CONV_EXCL=--argname=` - no need to type the `foobar` in. – AJM Jul 10 '23 at 11:59
  • 1
    re foobar - yes that's right. I added it to make it more visible that this is a prefix match against the whole string, not just a match against the argument name only. Maybe `--argname=fo` and `foob` in the other case would be a better eye catcher. – quetzalcoatl Jul 10 '23 at 12:02
  • 1
    re edit/improve - sure, please do. I wasn't going to compete in answers :) Also, your answer was one of those I initially found while searching for a solution, before I gathered enough keywords find find other sources, so by all means feel free to use anything I wrote here, literally or redacted, etc. – quetzalcoatl Jul 10 '23 at 12:05
  • regarding "strike" - I sense I missed something. Could you drop me a link to stack/meta or anything other that will explain things to me? – quetzalcoatl Jul 10 '23 at 12:06
  • @quetzalcoatl About the strike - https://openletter.mousetail.nl/ and https://meta.stackexchange.com/questions/389811/moderation-strike-stack-overflow-inc-cannot-consistently-ignore-mistreat-an are the starting points, with some later updates at https://meta.stackexchange.com/questions/390106/moderation-strike-update-data-dumps-choosing-representatives-gpt-data-and-wh . Jon Ericson has written quite a bit about it on his blog - try https://jlericson.com/2023/06/04/signing_on.html to start with. – AJM Jul 11 '23 at 09:38
  • Thank you for the links! – quetzalcoatl Jul 11 '23 at 18:44

4 Answers4

49

The release notes to the Git Bash 2.21.0 update today mentioned this as a known issue. Fortunately, they also described two solutions to the problem:

If you specify command-line options starting with a slash, POSIX-to-Windows path conversion will kick in converting e.g. "/usr/bin/bash.exe" to "C:\Program Files\Git\usr\bin\bash.exe". When that is not desired -- e.g. "--upload-pack=/opt/git/bin/git-upload-pack" or "-L/regex/" -- you need to set the environment variable MSYS_NO_PATHCONV temporarily, like so:

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

Alternatively, you can double the first slash to avoid POSIX-to-Windows path conversion, e.g. "//usr/bin/bash.exe".

However, MSYS_NO_PATHCONV=1 can cause problems if you're using a tilde ('~') to reprent your home folder:

$ 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:

In discussion with @quetzalcoatl in comments on my original question, MSYS2_ARG_CONV_EXCL="*" was suggested as an alternative to MSYS_NO_PATHCONV=1. I have tested this, and can confirm that it works just as well, but unfortunately also has the same problem with the ~ character.

Using information from

we can achieve a more fine-grained control, and eliminate the problem with ~. However, this comes at the cost of having to manually identify all of the various "arguments that look like Unix paths while they are not":

$ 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.
AJM
  • 1,317
  • 2
  • 15
  • 30
  • 10
    Using second alternative resulted in `req: Skipping unknown attribute "/C"`. Knowing this fixing it was simple with `"//x=1/C=SE/O=TEST"` so `x` was skipped instead. – s3c Jan 21 '21 at 14:20
  • 1
    I was going to edit in a link to the release notes that I mentioned. But it looks like there's only ever one copy of the release notes online and it's updated for every new version, so I couldn't reasonably say "these notes are for 2.21.0" any more. Anyway, you can find them at https://github.com/git-for-windows/build-extra/blob/main/ReleaseNotes.md – AJM Jun 27 '22 at 12:56
11

Using MSYS_NO_PATHCONV=1 can be problematic if your script accesses files.

Prefixing with a double forward slash doesn't work for the specific case of OpenSSL, as it causes the first DN segment key to be read as "/C" instead of "C", so OpenSSL drops it, outputting:

req: Skipping unknown attribute "/C"

Instead, I used a function that detects if running on bash for Windows, and prefixes with a "dummy" segment if so:

# 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")
Cocowalla
  • 13,822
  • 6
  • 66
  • 112
  • Interesting, my thanks for that. By the way, the double-forward-slash does work with OpenSSL in some situations, for example creating a cert with a zero-length Subject field: -subj "//" – AJM Feb 20 '20 at 12:08
  • Huh, I didn't even know it was possible to create a certificate with an empty DN! A bit OT, but does software work with such certificates? – Cocowalla Feb 20 '20 at 13:07
  • ARM's open source mbedTLS (tls.mbed.org) certainly does. But an empty issuer field is absolutely not allowed. – AJM Feb 20 '20 at 13:38
10

Found a workaround by passing a dummy value as the first attribute, for example: -subj '//SKIP=skip/C=gb/CN=foo'

5

I had the same issue using bash, but running the exact same command in Powershell worked for me. Hopefully this will help someone.

jtate
  • 2,612
  • 7
  • 25
  • 35