-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DarwinSSL + iOS / CFStringGetCString 128 char buffer too small for Asian locale #1823
Comments
That comment "Check if cacert is valid" seems kind of misleading, when I read that I thought some kind of comparison was supposed to occur there and instead it's only checking whether the subject can be converted to UTF-8. CopyCertSubject in darwinssl.c determines what it is the subject depending on the OS version and functions available. I don't think we can say for certain how big a subject will be. Instead we can allocate the space dynamically. I'm not entirely sure I'm using CFStringGetLength correctly here but it would probably look something like this: diff --git a/lib/vtls/darwinssl.c b/lib/vtls/darwinssl.c
index 18751ca..f511072 100644
--- a/lib/vtls/darwinssl.c
+++ b/lib/vtls/darwinssl.c
@@ -1888,18 +1888,25 @@ static int append_cert_to_array(struct Curl_easy *data,
return CURLE_SSL_CACERT;
}
- /* Check if cacert is valid. */
CFStringRef subject = CopyCertSubject(cacert);
if(subject) {
- char subject_cbuf[128];
- memset(subject_cbuf, 0, 128);
- if(!CFStringGetCString(subject,
- subject_cbuf,
- 128,
- kCFStringEncodingUTF8)) {
- CFRelease(cacert);
- failf(data, "SSL: invalid CA certificate subject");
- return CURLE_SSL_CACERT;
+ /* If subject is not UTF-8 then check if it can be converted */
+ if(!CFStringGetCStringPtr(subject, kCFStringEncodingUTF8)) {
+ size_t cbuf_size = ((size_t)CFStringGetLength(subject) * 4) + 1;
+ char *cbuf = calloc(cbuf_size, 1);
+ if(!cbuf) {
+ CFRelease(cacert);
+ failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(!CFStringGetCString(subject, cbuf, cbuf_size,
+ kCFStringEncodingUTF8)) {
+ free(cbuf);
+ CFRelease(cacert);
+ failf(data, "SSL: invalid CA certificate subject");
+ return CURLE_SSL_CACERT;
+ }
+ free(cbuf);
}
CFRelease(subject);
} CFStringGetCStringPtr as a speedup because I read here that if there's already that encoding available in the string it can just return it. CFStringGetLength questions because it returns CFIndex ( /cc @nickzman |
This tells me that your upper bound evaluation of the number of bytes required for the conversion as X * 4 + 1 is correct. Re: negative result, you could add an extra check for that (with better error string and return type than what's below). Maybe it's overkill and CFStringGetLength in practice can never return a negative number, but it's safer that way ?
Last but not least, should that same block of code be used everywhere in that file CFStringGetCString was used ? (I would say yes), to eliminate all the static 128 buffers ? It would be less efficient to dynamically allocate that memory, but it would be safer that way. |
Edited to fix mistakes. It is interesting to note in this particular case that @bsergean reported that the CA certificate subject is 125
When the device is set to English, It is interesting that a 127 byte buffer succeeds according to When the device is set to Chinese, The Chinese locale appears to work correctly. It is the many other languages that should be failing.
In light of the earlier mistakes and later comment, this theory doesn't fit in the slightest.
I will probably reach out to Apple for the buffer copying "succeeding" when it shouldn't. Perhaps the issue is already known though.
|
The 128 limit is used on multiple places in the darwinssl.c code so if one instance of it is deemed too small, it should probably be increased everywhere. Since this limit hasn't caused any problem before, it is probably rare with this large values so maybe that makes it OK to just double the value and keep the code simple |
As mentioned in the link provided by @jay, and the example I listed above. It appears So the proposal for |
The Unicode standard sometimes does terrible things in order to protect developers from even worse solutions. The proposal for (CFStringGetLength(subject)*4)+1 is better than what we currently have, and ought to solve this problem. |
... as the previous fixed length 128 bytes buffer was sometimes too small. Fixes #1823 Reported-by: Benjamin Sergeant Assisted-by: Bill Pyne, Ray Satiro, Nick Zitzmann
Please review my take at a function that attempts to handle all the fixed-size 128 bytes buffers in #1831. I'm sure I missed something. - I have not built all the possible combinations so some changes are not even compiled. |
Thanks! |
I did this
We are getting an error downloading a page through SSL with libcurl in our iOS app. This only happen when we hit a certain page with a certain certificate, and on Asian locales (simplified Chinese, Japanese).
The error message is
"SSL: invalid CA certificate subject"
, which come from this block of code:If I bump 128 to 256 everywhere in this file, the error goes away.
I expected the following
I should be able to download that page through SSL.
curl/libcurl version
curl-7.54.1
operating system
iOS
The text was updated successfully, but these errors were encountered: