Menu

#1196 with NSS, some certs unselectable via --cert name:passwd syntax

closed-fixed
nobody
SSL/TLS (37)
5
2013-06-21
2013-02-13
No

I need a way to tell the curl tool to use a certificate having a colon in its name.

With the curl tool, when I specify a client certificate to use via the -E or --cert switch, I can optionally specify a passphrase by appending a colon and the passphrase to the argument of the switch. In src/tool_getparam.c around line 1206, the first colon in the argument is found, using strchr, and everything after it is deemed to be the passphrase. Because of this decision, passphrases containing colons can be used, but certificates whose names contain colons cannot.

The use case is this: I've built curl against NSS, and I'm trying to use the certificate on my smartcard.

When you import a certificate from a file into an NSS database, it goes onto the token named "NSS Certificate DB." When you specify a certificate in the NSS database by its nickname, by default that certificate is sought on the "NSS Certificate DB" token. So if all you use with NSS is certificates you've imported from files, you never need a colon.

But if the certificate you want to use is stored on a different token (e.g., a smartcard), you have to name both the token and the certificate; the way to do so is with the syntax token:nickname - i.e. separating them by a colon. So the name of the certificate on my smartcard is "MY.FULL.NAME.1234567890:CAC ID Certificate".

Unfortunately when I hand that value to the -E switch, the curl tool parses that as a request to use the certificate named MY.FULL.NAME.1234567890, with the passphrase "CAC ID Certificate".

Discussion

  • jared jennings

    jared jennings - 2013-02-13

    Two ideas that likely won't work:

    1. Split the argument to -E on the last colon, not the first. This enables the specification of certificates with (multiple!) colons in their names, but breaks existing behavior by making passphrases with colons in them impossible to specify on the command line.

    2. Split on the first colon. If the certificate name thus obtained doesn't work, try splitting on the second colon, etc. The problem here is that figuring out the desired curl configuration given the command line switches and trying to connect using the configuration happen in very different parts of the code; bringing them together would be bad design and difficult to implement.

     
  • Dan Fandrich

    Dan Fandrich - 2013-02-13

    It may be possible to extend the syntax of this option to allow for escaping colons in the certificate name, and be mostly backward compatible. For example, URL escaping (%3a) or backslack escaping (\:). Neither % nor \ are likely to be used in certificate names, so this would be mostly compatible.

     
  • jared jennings

    jared jennings - 2013-02-13

    Dan, great idea. I realized most folks using backslashes in the argument to -E are probably trying to name a file under Windows. Any backslash-based escaping plan should make sure curl still acts how they expect. I think that means "\b" should evaluate to "\b", not "b": the backslash should only behave differently when followed by a backslash or a colon. Here's my attempt to thoroughly evaluate that.

    How curl acts right now:

    1a. -E 'foo:bar:baz' means cert foo with passphrase bar:baz.
    2a. -E 'foo\:bar:baz' means cert foo\ with passphrase bar:baz.
    3a. -E 'foo\\:bar:baz' means cert foo\\ with passphrase bar:baz.
    4a. -E 'foo:bar\:baz' means cert foo with passphrase bar\:baz.
    5a. -E 'foo:bar\\:baz' means cert foo with passphrase bar\\:baz.
    6a. -E 'foo\bar\baz' means cert foo\bar\baz.
    7a. -E 'foo\\bar\\baz' means cert foo\\bar\\baz.

    Proposed changes:

    1b. -E 'foo:bar:baz' as before means cert foo with passphrase bar:baz.
    2b. -E 'foo\:bar:baz' NEW means cert foo:bar with passphrase baz.
    3b. -E 'foo\\:bar:baz' NEW means cert foo\ with passphrase bar:baz.
    4b. -E 'foo:bar\:baz' as before means cert foo with passphrase bar\:baz.
    5b. -E 'foo:bar\\:baz' as before means cert foo with passphrase bar\\:baz.
    6b. -E 'foo\bar\baz' as before means cert foo\bar\baz.
    7b. -E 'foo\\bar\\baz' NEW means cert foo\bar\baz.

    When running under Windows, an ifdef comes into play, and we do not treat colons with backslashes just after them as cert:passphrase separators:

    1c. -E 'c:\foo:bar:baz' as before means cert c:\foo with passphrase bar:baz.
    2c. -E 'c:\foo\:bar:baz' NEW means cert c:\foo:bar with passphrase baz.
    3c. -E 'c:\foo\\:bar:baz' NEW means cert c:\foo\ with passphrase bar:baz.
    4c. -E 'c:\foo:bar\:baz' as before means cert c:\foo with passphrase bar\:baz.
    5c. -E 'c:\foo:bar\\:baz' as before means cert c:\foo with passphrase bar\\:baz.
    6c. -E 'c:\foo\bar\baz' as before means cert c:\foo\bar\baz.
    7c. -E 'c:\foo\\bar\\baz' NEW means cert c:\foo\bar\baz.

    The case I need is case 2b. The most important case where existing backslash behavior needs to be preserved is case 6c.

    curl's behavior would change backwards-incompatibly in case 2c, but it makes no sense to try to specify a Windows directory as a client certificate, so no one should fall into that case. Anyone who does would have to change and write the syntax under case 3c instead.

    Additionally cases 7b and 7c may be unexpected to anyone who has double backslashes in their cert names. I anticipate that this is rare.

    This behavior is unlike the behavior of the backslash in some other UNIX utilities, where the backslash always escapes the next character, but most escaped characters evaluate to themselves. This would make for these cases:

    1d. -E 'foo:bar:baz' as before means cert foo with passphrase bar:baz.
    2d. -E 'foo\:bar:baz' NEW means cert foo:bar with passphrase baz.
    3d. -E 'foo\\:bar:baz' NEW means cert foo\ with passphrase bar:baz.
    4d. -E 'foo:bar\:baz' as before means cert foo with passphrase bar\:baz.
    5d. -E 'foo:bar\\:baz' as before means cert foo with passphrase bar\\:baz.
    6d. -E 'foo\bar\baz' as before means cert foobarbaz.
    7d. -E 'foo\\bar\\baz' NEW means cert foo\bar\baz.

    I judge that 6d would be much more surprising to Windows users than 6b would be to POSIX users.

     

    Last edit: jared jennings 2013-02-13
  • jared jennings

    jared jennings - 2013-02-14

    A function that implements the above behavior, including the Windows ifdef, with tests, is in the attached source file, split_colons.c.

     
  • jared jennings

    jared jennings - 2013-02-14

    Patch against curl 7.29.0 allowing colons in certificate names by the means above.

     
  • Kamil Dudka

    Kamil Dudka - 2013-04-05

    Thank you for writing the patch! It looks good to me and I would like to merge it upstream. Could you please send me your name and e-mail so that I commit the patch with you as the author? Thanks in advance!

     
  • Daniel Stenberg

    Daniel Stenberg - 2013-05-06
    • labels: --> SSL/TLS
    • status: open --> closed-fixed
    • Group: --> not_used
     
  • Daniel Stenberg

    Daniel Stenberg - 2013-05-06

    Thanks, closing this issue!