Also "The most dangerous code in the world" is a bit misleading. I would say the code that runs a Predator drone is a little higher in the danger department.
But it's certainly thoughtless API design. The parameter sounds boolean (am I going to verify the SSL host or not?), and essentially it is, except that not verifying it for some reason takes two forms, and a true value turns out to specify one of them.
Whereas I doubt that the giftedness of the programmer has much to do with their reading the docs. A gifted programmer might assume that the API designer would do the same thing they would, which is to specify this with a boolean argument.
The problem isn't simply that VERIFY_HOST is documented as a scale from 0-2 that people are mistaking for a boolean by not reading the docs. The problem is that the scale is pointless, because the value it is expressing actually is a boolean: you are either verifying SSL certificates properly or you might as well not verify them at all. There is no real scale to express. The whole option actually documents a misunderstanding of SSL/TLS on the part of curl's author.
Which one's easier - fixing an API, or fixing most programmers?
@pmjordan @tqbf for test, and also for the same reason browser-users just click yes yes yes on cert dialogues
He seems like a nice guy and being the sole maintainer of Curl seems like a tough and probably unrewarding job. But that said, it's hard to shake the impression that VERIFYHOST=1 exists because people want to believe they're doing SSL/TLS securely, but have trouble getting it configured properly, and that VERIFYHOST=1 exists primarily to give people the feeling of having configured SSL/TLS well without making them actually do that.
API doc: "When the value is 1, the certificate must contain a Common Name field, but it doesn't matter what name it says. (This is not ordinarily a useful setting)."
[emphasis mine] It's hard to get clearer than that.
http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTS...
"Here's an option that you could reasonably expect to be boolean. And lo! the code appears to work if you treat it as a boolean. But, just to mess with you, I introduced an apparently useless option to handle the 'true' case in that boolean, and introduced an 'even truer' value that does what you expected".
This is simply a terrible, dangerous design. It is, like I said on Twitter today, a vulnerability in Curl, and one that should be fixed. The option expressed today by VERIFYHOST=1 should instead be the case when VERIFYHOST=-1 or VERIFYHOST=666. Meanwhile, VERIFYHOST=1 should, tomorrow if possible, do exactly what VERIFYHOST=2 does today.
The point of yours that I addressed was: "that VERIFYHOST=1 exists primarily to give people the feeling of having configured SSL/TLS well without making them actually do that."
Put simply: It does not exist primarily for that purpose.
I can't make it any clearer than that.
I'm kidding... I think.
You fail to provide any proof for that statement. The API doc merely states what the setting does, it says absolutely nothing about about its purpose, and neither do you.
> The default value for this option is 2.
In other words, there is absolutely no issue here. It does the right thing out of the box.
That's because experience shows if things are "grey" then someone can almost certainly break in.
It will only break servers and scripts that currently operate under a false sense of security. The maintainer should file a CVE, push the fixed version and let the distros sort out the rest. And he should do it ASAP.
Empirically, 0/1/2 either means no/yes/yes-and-something-obscure-on-top-of-that, or, worse, as in this case, no/kind-of-but-not-really/yes.
enum Bool {
True,
False,
FileNotFound
};
This would have been much safer as separate AUTHENTICATE_CERT (which checks the CA sig and expiry and revocation) and VERIFY_CERT_COMMON_NAME options, both of which default to true. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
I and any normal developer is going to think "oh, this is important, I'd better make sure to leave it in there."Configuration audits aren't as expensive as code audits, but they are still expensive.
That is, failure should take effort. Dangerous options should be more laborious to express. The happy path should be the most concise and straightforward path.
It takes more effort to override the default and shoot yourself in the foot.
Granted, it could be better. I guess that strange option could be a completely separate command parameter with a very obvious name. Then again, it's such a strange behaviour, maybe it just shouldn't even be an option at all.
This API doesn't fit with the philosophy because it takes a negligible amount of work to walk down the unsafe path.
When designing the Curl API, it should have been obvious that VERIFYHOST is likely be set incorrectly, especially once it's used in languages that coerce true to 1.
Sometimes it's just because I like to be explicit and sometimes I'm concerned about the default being changed in a future version of the library or due to a server with a different config.
Not to mention that a lot of code ends up on the internet and is often blindly copied and pasted by programmers in a rush.
Curl has an option, CURL_SSL_VERIFYHOST. When VERIFYHOST=0, Curl does what you'd expect: it effectively doesn't validate SSL certificates.
When VERIFYHOST=2, Curl does what you'd expect: it verifies SSL certificates, ensuring that one of the hosts attested by the certificate matches the host presenting it.
When VERIFYHOST=1, or, in some popular languages, when VERIFYHOST=TRUE, Curl does something very strange. It checks to see if the certificate attests to any hostnames, and then accepts the certificate no matter who presents it.
Developers reasonably assume parameters like "VERIFYHOST" are boolean; either we're verifying or we're not. So they routinely set VERIFYHOST to 1 or "true" (which can promote to 1). Because Curl has this weird in-between setting, which does not express any security policy I can figure out, they're effectively not verifying certificates.