136136/* The last #include file should be: */
137137#include "memdebug.h"
138138
139+
140+ #define DEBUG_CF 0
141+
142+ #if DEBUG_CF
143+ #define CF_DEBUGF (x ) x
144+ #else
145+ #define CF_DEBUGF (x ) do { } while(0)
146+ #endif
147+
139148/* From MacTypes.h (which we can't include because it isn't present in iOS: */
140149#define ioErr -36
141150#define paramErr -50
@@ -838,6 +847,8 @@ static OSStatus bio_cf_in_read(SSLConnectionRef connection,
838847
839848 DEBUGASSERT (data );
840849 nread = Curl_conn_cf_recv (cf -> next , data , buf , * dataLength , & result );
850+ CF_DEBUGF (infof (data , CFMSG (cf , "bio_read(len=%zu) -> %zd, result=%d" ),
851+ * dataLength , nread , result ));
841852 if (nread < 0 ) {
842853 switch (result ) {
843854 case CURLE_OK :
@@ -851,6 +862,9 @@ static OSStatus bio_cf_in_read(SSLConnectionRef connection,
851862 }
852863 nread = 0 ;
853864 }
865+ else if ((size_t )nread < * dataLength ) {
866+ rtn = errSSLWouldBlock ;
867+ }
854868 * dataLength = nread ;
855869 return rtn ;
856870}
@@ -865,22 +879,27 @@ static OSStatus bio_cf_out_write(SSLConnectionRef connection,
865879 struct Curl_easy * data = connssl -> call_data ;
866880 ssize_t nwritten ;
867881 CURLcode result ;
868- OSStatus ortn = noErr ;
882+ OSStatus rtn = noErr ;
869883
870884 DEBUGASSERT (data );
871885 nwritten = Curl_conn_cf_send (cf -> next , data , buf , * dataLength , & result );
886+ CF_DEBUGF (infof (data , CFMSG (cf , "bio_send(len=%zu) -> %zd, result=%d" ),
887+ * dataLength , nwritten , result ));
872888 if (nwritten <= 0 ) {
873889 if (result == CURLE_AGAIN ) {
874- ortn = errSSLWouldBlock ;
890+ rtn = errSSLWouldBlock ;
875891 backend -> ssl_direction = true;
876892 }
877893 else {
878- ortn = ioErr ;
894+ rtn = ioErr ;
879895 }
880896 nwritten = 0 ;
881897 }
898+ else if ((size_t )nwritten < * dataLength ) {
899+ rtn = errSSLWouldBlock ;
900+ }
882901 * dataLength = nwritten ;
883- return ortn ;
902+ return rtn ;
884903}
885904
886905#ifndef CURL_DISABLE_VERBOSE_STRINGS
@@ -1638,6 +1657,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
16381657
16391658 DEBUGASSERT (backend );
16401659
1660+ CF_DEBUGF (infof (data , CFMSG (cf , "connect_step1" )));
16411661 GetDarwinVersionNumber (& darwinver_maj , & darwinver_min );
16421662#endif /* CURL_BUILD_MAC */
16431663
@@ -2236,15 +2256,21 @@ static int append_cert_to_array(struct Curl_easy *data,
22362256 return CURLE_OK ;
22372257}
22382258
2239- static CURLcode verify_cert_buf (struct Curl_easy * data ,
2259+ static CURLcode verify_cert_buf (struct Curl_cfilter * cf ,
2260+ struct Curl_easy * data ,
22402261 const unsigned char * certbuf , size_t buflen ,
22412262 SSLContextRef ctx )
22422263{
22432264 int n = 0 , rc ;
22442265 long res ;
22452266 unsigned char * der ;
22462267 size_t derlen , offset = 0 ;
2247-
2268+ OSStatus ret ;
2269+ SecTrustResultType trust_eval ;
2270+ CFMutableArrayRef array = NULL ;
2271+ SecTrustRef trust = NULL ;
2272+ CURLcode result = CURLE_PEER_FAILED_VERIFICATION ;
2273+ (void )cf ;
22482274 /*
22492275 * Certbuf now contains the contents of the certificate file, which can be
22502276 * - a single DER certificate,
@@ -2254,11 +2280,11 @@ static CURLcode verify_cert_buf(struct Curl_easy *data,
22542280 * Go through certbuf, and convert any PEM certificate in it into DER
22552281 * format.
22562282 */
2257- CFMutableArrayRef array = CFArrayCreateMutable (kCFAllocatorDefault , 0 ,
2258- & kCFTypeArrayCallBacks );
2283+ array = CFArrayCreateMutable (kCFAllocatorDefault , 0 , & kCFTypeArrayCallBacks );
22592284 if (!array ) {
22602285 failf (data , "SSL: out of memory creating CA certificate array" );
2261- return CURLE_OUT_OF_MEMORY ;
2286+ result = CURLE_OUT_OF_MEMORY ;
2287+ goto out ;
22622288 }
22632289
22642290 while (offset < buflen ) {
@@ -2270,19 +2296,20 @@ static CURLcode verify_cert_buf(struct Curl_easy *data,
22702296 */
22712297 res = pem_to_der ((const char * )certbuf + offset , & der , & derlen );
22722298 if (res < 0 ) {
2273- CFRelease (array );
22742299 failf (data , "SSL: invalid CA certificate #%d (offset %zu) in bundle" ,
22752300 n , offset );
2276- return CURLE_SSL_CACERT_BADFILE ;
2301+ result = CURLE_SSL_CACERT_BADFILE ;
2302+ goto out ;
22772303 }
22782304 offset += res ;
22792305
22802306 if (res == 0 && offset == 0 ) {
22812307 /* This is not a PEM file, probably a certificate in DER format. */
22822308 rc = append_cert_to_array (data , certbuf , buflen , array );
22832309 if (rc != CURLE_OK ) {
2284- CFRelease (array );
2285- return rc ;
2310+ CF_DEBUGF (infof (data , CFMSG (cf , "append_cert for CA failed" )));
2311+ result = rc ;
2312+ goto out ;
22862313 }
22872314 break ;
22882315 }
@@ -2294,63 +2321,73 @@ static CURLcode verify_cert_buf(struct Curl_easy *data,
22942321 rc = append_cert_to_array (data , der , derlen , array );
22952322 free (der );
22962323 if (rc != CURLE_OK ) {
2297- CFRelease (array );
2298- return rc ;
2324+ CF_DEBUGF (infof (data , CFMSG (cf , "append_cert for CA failed" )));
2325+ result = rc ;
2326+ goto out ;
22992327 }
23002328 }
23012329
2302- SecTrustRef trust ;
2303- OSStatus ret = SSLCopyPeerTrust (ctx , & trust );
2330+ ret = SSLCopyPeerTrust (ctx , & trust );
23042331 if (!trust ) {
23052332 failf (data , "SSL: error getting certificate chain" );
2306- CFRelease (array );
2307- return CURLE_PEER_FAILED_VERIFICATION ;
2333+ goto out ;
23082334 }
23092335 else if (ret != noErr ) {
2310- CFRelease (array );
23112336 failf (data , "SSLCopyPeerTrust() returned error %d" , ret );
2312- return CURLE_PEER_FAILED_VERIFICATION ;
2337+ goto out ;
23132338 }
23142339
2340+ CF_DEBUGF (infof (data , CFMSG (cf , "setting %d trust anchors" ), n ));
23152341 ret = SecTrustSetAnchorCertificates (trust , array );
23162342 if (ret != noErr ) {
2317- CFRelease (array );
2318- CFRelease (trust );
23192343 failf (data , "SecTrustSetAnchorCertificates() returned error %d" , ret );
2320- return CURLE_PEER_FAILED_VERIFICATION ;
2344+ goto out ;
23212345 }
23222346 ret = SecTrustSetAnchorCertificatesOnly (trust , true);
23232347 if (ret != noErr ) {
2324- CFRelease (array );
2325- CFRelease (trust );
23262348 failf (data , "SecTrustSetAnchorCertificatesOnly() returned error %d" , ret );
2327- return CURLE_PEER_FAILED_VERIFICATION ;
2349+ goto out ;
23282350 }
23292351
2330- SecTrustResultType trust_eval = 0 ;
2352+ trust_eval = 0 ;
23312353 ret = SecTrustEvaluate (trust , & trust_eval );
2332- CFRelease (array );
2333- CFRelease (trust );
23342354 if (ret != noErr ) {
23352355 failf (data , "SecTrustEvaluate() returned error %d" , ret );
2336- return CURLE_PEER_FAILED_VERIFICATION ;
2356+ goto out ;
23372357 }
23382358
23392359 switch (trust_eval ) {
23402360 case kSecTrustResultUnspecified :
2361+ /* what does this really mean? */
2362+ CF_DEBUGF (infof (data , CFMSG (cf , "trust result: Unspecified" )));
2363+ result = CURLE_OK ;
2364+ goto out ;
23412365 case kSecTrustResultProceed :
2342- return CURLE_OK ;
2366+ CF_DEBUGF (infof (data , CFMSG (cf , "trust result: Proceed" )));
2367+ result = CURLE_OK ;
2368+ goto out ;
23432369
23442370 case kSecTrustResultRecoverableTrustFailure :
2371+ failf (data , "SSL: peer not verified: RecoverableTrustFailure" );
2372+ goto out ;
23452373 case kSecTrustResultDeny :
2374+ failf (data , "SSL: peer not verified: Deny" );
2375+ goto out ;
23462376 default :
2347- failf (data , "SSL: certificate verification failed (result: %d)" ,
2348- trust_eval );
2349- return CURLE_PEER_FAILED_VERIFICATION ;
2377+ failf (data , "SSL: perr not verified: result=%d" , trust_eval );
2378+ goto out ;
23502379 }
2380+
2381+ out :
2382+ if (trust )
2383+ CFRelease (trust );
2384+ if (array )
2385+ CFRelease (array );
2386+ return result ;
23512387}
23522388
2353- static CURLcode verify_cert (struct Curl_easy * data , const char * cafile ,
2389+ static CURLcode verify_cert (struct Curl_cfilter * cf ,
2390+ struct Curl_easy * data , const char * cafile ,
23542391 const struct curl_blob * ca_info_blob ,
23552392 SSLContextRef ctx )
23562393{
@@ -2359,6 +2396,7 @@ static CURLcode verify_cert(struct Curl_easy *data, const char *cafile,
23592396 size_t buflen ;
23602397
23612398 if (ca_info_blob ) {
2399+ CF_DEBUGF (infof (data , CFMSG (cf , "verify_peer, CA from config blob" )));
23622400 certbuf = (unsigned char * )malloc (ca_info_blob -> len + 1 );
23632401 if (!certbuf ) {
23642402 return CURLE_OUT_OF_MEMORY ;
@@ -2368,6 +2406,8 @@ static CURLcode verify_cert(struct Curl_easy *data, const char *cafile,
23682406 certbuf [ca_info_blob -> len ]= '\0' ;
23692407 }
23702408 else if (cafile ) {
2409+ CF_DEBUGF (infof (data , CFMSG (cf , "verify_peer, CA from file '%s'" ),
2410+ cafile ));
23712411 if (read_cert (cafile , & certbuf , & buflen ) < 0 ) {
23722412 failf (data , "SSL: failed to read or invalid CA certificate" );
23732413 return CURLE_SSL_CACERT_BADFILE ;
@@ -2376,7 +2416,7 @@ static CURLcode verify_cert(struct Curl_easy *data, const char *cafile,
23762416 else
23772417 return CURLE_SSL_CACERT_BADFILE ;
23782418
2379- result = verify_cert_buf (data , certbuf , buflen , ctx );
2419+ result = verify_cert_buf (cf , data , certbuf , buflen , ctx );
23802420 free (certbuf );
23812421 return result ;
23822422}
@@ -2503,8 +2543,10 @@ static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
25032543 || ssl_connect_2_reading == connssl -> connecting_state
25042544 || ssl_connect_2_writing == connssl -> connecting_state );
25052545 DEBUGASSERT (backend );
2546+ CF_DEBUGF (infof (data , CFMSG (cf , "connect_step2" )));
25062547
25072548 /* Here goes nothing: */
2549+ check_handshake :
25082550 err = SSLHandshake (backend -> ssl_ctx );
25092551
25102552 if (err != noErr ) {
@@ -2519,14 +2561,14 @@ static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
25192561 case -9841 :
25202562 if ((conn_config -> CAfile || conn_config -> ca_info_blob ) &&
25212563 conn_config -> verifypeer ) {
2522- CURLcode result = verify_cert (data , conn_config -> CAfile ,
2564+ CURLcode result = verify_cert (cf , data , conn_config -> CAfile ,
25232565 conn_config -> ca_info_blob ,
25242566 backend -> ssl_ctx );
25252567 if (result )
25262568 return result ;
25272569 }
25282570 /* the documentation says we need to call SSLHandshake() again */
2529- return sectransp_connect_step2 ( cf , data ) ;
2571+ goto check_handshake ;
25302572
25312573 /* Problem with encrypt / decrypt */
25322574 case errSSLPeerDecodeError :
@@ -2966,6 +3008,7 @@ static CURLcode sectransp_connect_step3(struct Curl_cfilter *cf,
29663008{
29673009 struct ssl_connect_data * connssl = cf -> ctx ;
29683010
3011+ CF_DEBUGF (infof (data , CFMSG (cf , "connect_step3" )));
29693012 /* There is no step 3!
29703013 * Well, okay, let's collect server certificates, and if verbose mode is on,
29713014 * let's print the details of the server certificates. */
@@ -3074,6 +3117,7 @@ sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
30743117 }
30753118
30763119 if (ssl_connect_done == connssl -> connecting_state ) {
3120+ CF_DEBUGF (infof (data , CFMSG (cf , "connected" )));
30773121 connssl -> state = ssl_connection_complete ;
30783122 * done = TRUE;
30793123 }
@@ -3119,6 +3163,7 @@ static void sectransp_close(struct Curl_cfilter *cf, struct Curl_easy *data)
31193163 DEBUGASSERT (backend );
31203164
31213165 if (backend -> ssl_ctx ) {
3166+ CF_DEBUGF (infof (data , CFMSG (cf , "close" )));
31223167 (void )SSLClose (backend -> ssl_ctx );
31233168#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
31243169 if (SSLCreateContext )
@@ -3162,6 +3207,7 @@ static int sectransp_shutdown(struct Curl_cfilter *cf,
31623207
31633208 what = SOCKET_READABLE (cf -> conn -> sock [cf -> sockindex ], SSL_SHUTDOWN_TIMEOUT );
31643209
3210+ CF_DEBUGF (infof (data , CFMSG (cf , "shutdown" )));
31653211 while (loop -- ) {
31663212 if (what < 0 ) {
31673213 /* anything that gets here is fatally bad */
@@ -3230,6 +3276,7 @@ static int sectransp_check_cxn(struct Curl_cfilter *cf,
32303276 DEBUGASSERT (backend );
32313277
32323278 if (backend -> ssl_ctx ) {
3279+ CF_DEBUGF (infof (data , CFMSG (cf , "check connection" )));
32333280 err = SSLGetSessionState (backend -> ssl_ctx , & state );
32343281 if (err == noErr )
32353282 return state == kSSLConnected || state == kSSLHandshake ;
@@ -3250,6 +3297,7 @@ static bool sectransp_data_pending(struct Curl_cfilter *cf,
32503297 DEBUGASSERT (backend );
32513298
32523299 if (backend -> ssl_ctx ) { /* SSL is in use */
3300+ CF_DEBUGF (infof (data , CFMSG (cf , "data_pending" )));
32533301 err = SSLGetBufferedReadSize (backend -> ssl_ctx , & buffer );
32543302 if (err == noErr )
32553303 return buffer > 0UL ;
@@ -3407,7 +3455,7 @@ static ssize_t sectransp_recv(struct Curl_cfilter *cf,
34073455 case -9841 :
34083456 if ((conn_config -> CAfile || conn_config -> ca_info_blob ) &&
34093457 conn_config -> verifypeer ) {
3410- CURLcode result = verify_cert (data , conn_config -> CAfile ,
3458+ CURLcode result = verify_cert (cf , data , conn_config -> CAfile ,
34113459 conn_config -> ca_info_blob ,
34123460 backend -> ssl_ctx );
34133461 if (result )
0 commit comments