patches: update lighttpd patches
[git-osx-installer.git] / patches / curl / curl_darwinssl_macosx.c
blobd584b6a7c9b5444f1fbce23800a1d4f752e7e701
1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
9 * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
11 * MacOSX modifications copyright (C) 2014, 2015 Kyle J. McKay.
12 * All rights reserved.
14 * This software is licensed as described in the file COPYING, which
15 * you should have received as part of this distribution. The terms
16 * are also available at http://curl.haxx.se/docs/copyright.html.
18 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
19 * copies of the Software, and permit persons to whom the Software is
20 * furnished to do so, under the terms of the COPYING file.
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
25 ***************************************************************************/
28 * Source file for all iOS and Mac OS X SecureTransport-specific code for the
29 * TLS/SSL layer. No code but vtls.c should ever call or use these functions.
33 * CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST have various interactions
34 * with SSLSetPeerDomainName and TLS SNI. TLS SNI is only available under
35 * SecureTransport when running on OS X 10.5.6 or later and
36 * SSLSetPeerDomainName has been called. Note that RFC 6066 section 3 forbids
37 * sending a literal IPv4 or IPv6 address in SNI, so SSLSetPeerDomainName is
38 * never called in that case, otherwise it is ALWAYS called if a non-empty host
39 * name is given -- otherwise we could get back the wrong server certificate!
40 * And calling SSLSetPeerDomainName causes host name verification to occur.
41 * (The host name should always be non-empty otherwise we wouldn't have
42 * anything to connect to.)
44 * So in practice this means it's not possible to verify the peer without also
45 * verifying the host name, because if you ignore the errSSLHostNameMismatch
46 * error, you don't know if there would have been a subsequent error or not so
47 * you can't just turn that into no error.
49 * It is possible, however, to do the reverse and ignore any SecureTransport
50 * certificate validation errors and as long as we get at least one certificate
51 * from the peer we can verify the host name matches even if something's wrong
52 * with the certificate chain validation.
54 * VERIFYPEER VERIFYHOST Result
55 * ---------- ---------- ----------------------------------------------------
56 * disabled disabled SNI still sent for DNS host names
57 * disabled enabled Peer's first cert must match the host DNS or IP name
58 * enabled disabled DNS host name matching still occurs, IP does not
59 * enabled enabled Peer's first cert must match the host DNS or IP name
61 * The certificate chain is ALWAYS checked if VERIFYPEER is enabled.
63 * Note that CURLOPT_PINNEDPUBLICKEY matching ALWAYS takes place if the option
64 * is set. It's done as the final step and requires the peer to send at least
65 * one certificate.
68 #include "curl_setup.h"
70 #include "urldata.h" /* for the SessionHandle definition */
72 #ifdef USE_DARWINSSL
74 #include <CoreFoundation/CoreFoundation.h>
75 #include <CommonCrypto/CommonDigest.h>
76 #include <Security/Security.h>
77 #include <Security/SecureTransport.h>
78 #include <Security/SecCertificate.h>
79 #include <Security/SecTrust.h>
80 #include <Security/SecImportExport.h>
82 /* The SecureTransport compatibility layer is separate */
83 #include "stcompat.h"
85 /* The Security framework has changed greatly between different OS X
86 versions, and we will try to support as many of them as we can (back to
87 Tiger) by using a compatibility layer.
89 IMPORTANT: TLS 1.1 and 1.2 support are detected at runtime, and
90 will automatically activate if run on 10.8 or later. */
92 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
94 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040
95 #error "The darwinssl macosx back-end requires Tiger or later."
96 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1040 */
98 #ifndef kCFCoreFoundationVersionNumber10_8
99 #define kCFCoreFoundationVersionNumber10_8 744.00
100 #endif
101 #ifndef kCFCoreFoundationVersionNumber10_8_3
102 #define kCFCoreFoundationVersionNumber10_8_3 744.18
103 #endif
104 #ifndef kCFCoreFoundationVersionNumber10_9
105 #define kCFCoreFoundationVersionNumber10_9 855.11
106 #endif
108 #elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
110 #error iOS is not currently supported by this version of the darwinssl back-end
112 #else
114 #error the darwinssl macosx back-end requires Mac OS X
116 #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
118 #include "urldata.h"
119 #include "sendf.h"
120 #include "inet_pton.h"
121 #include "connect.h"
122 #include "select.h"
123 #include "vtls.h"
124 #if LIBCURL_VERSION_NUM >= 0x072900
125 #include "darwinssl.h"
126 #else
127 #include "curl_darwinssl.h"
128 #endif
130 #define _MPRINTF_REPLACE /* use our functions only */
131 #include <curl/mprintf.h>
133 #include "curl_memory.h"
134 /* The last #include file should be: */
135 #include "memdebug.h"
137 /* The following two functions were ripped from Apple sample code,
138 * with some modifications: */
139 static OSStatus SocketRead(SSLConnectionRef connection,
140 void *data, /* owned by
141 * caller, data
142 * RETURNED */
143 size_t *dataLength) /* IN/OUT */
145 size_t bytesToGo = *dataLength;
146 size_t initLen = bytesToGo;
147 UInt8 *currData = (UInt8 *)data;
148 /*int sock = *(int *)connection;*/
149 struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
150 int sock = connssl->ssl_sockfd;
151 OSStatus rtn = noErr;
152 size_t bytesRead;
153 ssize_t rrtn;
154 int theErr;
156 *dataLength = 0;
158 for(;;) {
159 bytesRead = 0;
160 rrtn = read(sock, currData, bytesToGo);
161 if(rrtn <= 0) {
162 /* this is guesswork... */
163 theErr = errno;
164 if(rrtn == 0) { /* EOF = server hung up */
165 /* the framework will turn this into errSSLClosedNoNotify */
166 rtn = errSSLClosedGraceful;
168 else /* do the switch */
169 switch(theErr) {
170 case ENOENT:
171 /* connection closed */
172 rtn = errSSLClosedGraceful;
173 break;
174 case ECONNRESET:
175 rtn = errSSLClosedAbort;
176 break;
177 case EAGAIN:
178 rtn = errSSLWouldBlock;
179 connssl->ssl_direction = false;
180 break;
181 default:
182 rtn = ioErr;
183 break;
185 break;
187 else {
188 bytesRead = rrtn;
190 bytesToGo -= bytesRead;
191 currData += bytesRead;
193 if(bytesToGo == 0) {
194 /* filled buffer with incoming data, done */
195 break;
198 *dataLength = initLen - bytesToGo;
200 return rtn;
203 static OSStatus SocketWrite(SSLConnectionRef connection,
204 const void *data,
205 size_t *dataLength) /* IN/OUT */
207 size_t bytesSent = 0;
208 /*int sock = *(int *)connection;*/
209 struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
210 int sock = connssl->ssl_sockfd;
211 ssize_t length;
212 size_t dataLen = *dataLength;
213 const UInt8 *dataPtr = (UInt8 *)data;
214 OSStatus ortn;
215 int theErr;
217 *dataLength = 0;
219 do {
220 length = write(sock,
221 (char*)dataPtr + bytesSent,
222 dataLen - bytesSent);
223 } while((length > 0) &&
224 ( (bytesSent += length) < dataLen) );
226 if(length <= 0) {
227 theErr = errno;
228 if(theErr == EAGAIN) {
229 ortn = errSSLWouldBlock;
230 connssl->ssl_direction = true;
232 else {
233 ortn = ioErr;
236 else {
237 ortn = noErr;
239 *dataLength = bytesSent;
240 return ortn;
243 CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
244 switch (cipher) {
245 #define CIPHER(x) case x: return #x
246 /* SSL version 3.0 */
247 CIPHER(SSL_RSA_WITH_NULL_MD5);
248 CIPHER(SSL_RSA_WITH_NULL_SHA);
249 CIPHER(SSL_RSA_EXPORT_WITH_RC4_40_MD5);
250 CIPHER(SSL_RSA_WITH_RC4_128_MD5);
251 CIPHER(SSL_RSA_WITH_RC4_128_SHA);
252 CIPHER(SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5);
253 CIPHER(SSL_RSA_WITH_IDEA_CBC_SHA);
254 CIPHER(SSL_RSA_EXPORT_WITH_DES40_CBC_SHA);
255 CIPHER(SSL_RSA_WITH_DES_CBC_SHA);
256 CIPHER(SSL_RSA_WITH_3DES_EDE_CBC_SHA);
257 CIPHER(SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA);
258 CIPHER(SSL_DH_DSS_WITH_DES_CBC_SHA);
259 CIPHER(SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA);
260 CIPHER(SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA);
261 CIPHER(SSL_DH_RSA_WITH_DES_CBC_SHA);
262 CIPHER(SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA);
263 CIPHER(SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA);
264 CIPHER(SSL_DHE_DSS_WITH_DES_CBC_SHA);
265 CIPHER(SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA);
266 CIPHER(SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA);
267 CIPHER(SSL_DHE_RSA_WITH_DES_CBC_SHA);
268 CIPHER(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA);
269 CIPHER(SSL_DH_anon_EXPORT_WITH_RC4_40_MD5);
270 CIPHER(SSL_DH_anon_WITH_RC4_128_MD5);
271 CIPHER(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA);
272 CIPHER(SSL_DH_anon_WITH_DES_CBC_SHA);
273 CIPHER(SSL_DH_anon_WITH_3DES_EDE_CBC_SHA);
274 CIPHER(SSL_FORTEZZA_DMS_WITH_NULL_SHA);
275 CIPHER(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA);
276 /* TLS 1.0 with AES (RFC 3268)
277 (Apparently these are used in SSLv3 implementations as well.) */
278 CIPHER(TLS_RSA_WITH_AES_128_CBC_SHA);
279 CIPHER(TLS_DH_DSS_WITH_AES_128_CBC_SHA);
280 CIPHER(TLS_DH_RSA_WITH_AES_128_CBC_SHA);
281 CIPHER(TLS_DHE_DSS_WITH_AES_128_CBC_SHA);
282 CIPHER(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
283 CIPHER(TLS_DH_anon_WITH_AES_128_CBC_SHA);
284 CIPHER(TLS_RSA_WITH_AES_256_CBC_SHA);
285 CIPHER(TLS_DH_DSS_WITH_AES_256_CBC_SHA);
286 CIPHER(TLS_DH_RSA_WITH_AES_256_CBC_SHA);
287 CIPHER(TLS_DHE_DSS_WITH_AES_256_CBC_SHA);
288 CIPHER(TLS_DHE_RSA_WITH_AES_256_CBC_SHA);
289 CIPHER(TLS_DH_anon_WITH_AES_256_CBC_SHA);
290 /* SSL version 2.0 */
291 CIPHER(SSL_RSA_WITH_RC2_CBC_MD5);
292 CIPHER(SSL_RSA_WITH_IDEA_CBC_MD5);
293 CIPHER(SSL_RSA_WITH_DES_CBC_MD5);
294 CIPHER(SSL_RSA_WITH_3DES_EDE_CBC_MD5);
295 #undef CIPHER
297 return "SSL_NULL_WITH_NULL_NULL";
300 CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
301 switch(cipher) {
302 #define CIPHER(x) case x: return #x
303 CIPHER(TLS_RSA_WITH_NULL_MD5);
304 CIPHER(TLS_RSA_WITH_NULL_SHA);
305 CIPHER(SSL_RSA_EXPORT_WITH_RC4_40_MD5);
306 CIPHER(TLS_RSA_WITH_RC4_128_MD5);
307 CIPHER(TLS_RSA_WITH_RC4_128_SHA);
308 CIPHER(SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5);
309 CIPHER(SSL_RSA_WITH_IDEA_CBC_SHA);
310 CIPHER(SSL_RSA_EXPORT_WITH_DES40_CBC_SHA);
311 CIPHER(SSL_RSA_WITH_DES_CBC_SHA);
312 CIPHER(TLS_RSA_WITH_3DES_EDE_CBC_SHA);
313 CIPHER(SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA);
314 CIPHER(SSL_DH_DSS_WITH_DES_CBC_SHA);
315 CIPHER(TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA);
316 CIPHER(SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA);
317 CIPHER(SSL_DH_RSA_WITH_DES_CBC_SHA);
318 CIPHER(TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA);
319 CIPHER(SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA);
320 CIPHER(SSL_DHE_DSS_WITH_DES_CBC_SHA);
321 CIPHER(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA);
322 CIPHER(SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA);
323 CIPHER(SSL_DHE_RSA_WITH_DES_CBC_SHA);
324 CIPHER(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA);
325 CIPHER(SSL_DH_anon_EXPORT_WITH_RC4_40_MD5);
326 CIPHER(TLS_DH_anon_WITH_RC4_128_MD5);
327 CIPHER(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA);
328 CIPHER(SSL_DH_anon_WITH_DES_CBC_SHA);
329 CIPHER(TLS_DH_anon_WITH_3DES_EDE_CBC_SHA);
330 CIPHER(SSL_FORTEZZA_DMS_WITH_NULL_SHA);
331 CIPHER(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA);
332 CIPHER(TLS_PSK_WITH_NULL_SHA);
333 CIPHER(TLS_DHE_PSK_WITH_NULL_SHA);
334 CIPHER(TLS_RSA_PSK_WITH_NULL_SHA);
335 CIPHER(TLS_RSA_WITH_AES_128_CBC_SHA);
336 CIPHER(TLS_DH_DSS_WITH_AES_128_CBC_SHA);
337 CIPHER(TLS_DH_RSA_WITH_AES_128_CBC_SHA);
338 CIPHER(TLS_DHE_DSS_WITH_AES_128_CBC_SHA);
339 CIPHER(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
340 CIPHER(TLS_DH_anon_WITH_AES_128_CBC_SHA);
341 CIPHER(TLS_RSA_WITH_AES_256_CBC_SHA);
342 CIPHER(TLS_DH_DSS_WITH_AES_256_CBC_SHA);
343 CIPHER(TLS_DH_RSA_WITH_AES_256_CBC_SHA);
344 CIPHER(TLS_DHE_DSS_WITH_AES_256_CBC_SHA);
345 CIPHER(TLS_DHE_RSA_WITH_AES_256_CBC_SHA);
346 CIPHER(TLS_DH_anon_WITH_AES_256_CBC_SHA);
347 CIPHER(TLS_RSA_WITH_NULL_SHA256);
348 CIPHER(TLS_RSA_WITH_AES_128_CBC_SHA256);
349 CIPHER(TLS_RSA_WITH_AES_256_CBC_SHA256);
350 CIPHER(TLS_DH_DSS_WITH_AES_128_CBC_SHA256);
351 CIPHER(TLS_DH_RSA_WITH_AES_128_CBC_SHA256);
352 CIPHER(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256);
353 CIPHER(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256);
354 CIPHER(TLS_DH_DSS_WITH_AES_256_CBC_SHA256);
355 CIPHER(TLS_DH_RSA_WITH_AES_256_CBC_SHA256);
356 CIPHER(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256);
357 CIPHER(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256);
358 CIPHER(TLS_DH_anon_WITH_AES_128_CBC_SHA256);
359 CIPHER(TLS_DH_anon_WITH_AES_256_CBC_SHA256);
360 CIPHER(TLS_PSK_WITH_RC4_128_SHA);
361 CIPHER(TLS_PSK_WITH_3DES_EDE_CBC_SHA);
362 CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA);
363 CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA);
364 CIPHER(TLS_DHE_PSK_WITH_RC4_128_SHA);
365 CIPHER(TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA);
366 CIPHER(TLS_DHE_PSK_WITH_AES_128_CBC_SHA);
367 CIPHER(TLS_DHE_PSK_WITH_AES_256_CBC_SHA);
368 CIPHER(TLS_RSA_PSK_WITH_RC4_128_SHA);
369 CIPHER(TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA);
370 CIPHER(TLS_RSA_PSK_WITH_AES_128_CBC_SHA);
371 CIPHER(TLS_RSA_PSK_WITH_AES_256_CBC_SHA);
372 CIPHER(TLS_RSA_WITH_AES_128_GCM_SHA256);
373 CIPHER(TLS_RSA_WITH_AES_256_GCM_SHA384);
374 CIPHER(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256);
375 CIPHER(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384);
376 CIPHER(TLS_DH_RSA_WITH_AES_128_GCM_SHA256);
377 CIPHER(TLS_DH_RSA_WITH_AES_256_GCM_SHA384);
378 CIPHER(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256);
379 CIPHER(TLS_DHE_DSS_WITH_AES_256_GCM_SHA384);
380 CIPHER(TLS_DH_DSS_WITH_AES_128_GCM_SHA256);
381 CIPHER(TLS_DH_DSS_WITH_AES_256_GCM_SHA384);
382 CIPHER(TLS_DH_anon_WITH_AES_128_GCM_SHA256);
383 CIPHER(TLS_DH_anon_WITH_AES_256_GCM_SHA384);
384 CIPHER(TLS_PSK_WITH_AES_128_GCM_SHA256);
385 CIPHER(TLS_PSK_WITH_AES_256_GCM_SHA384);
386 CIPHER(TLS_DHE_PSK_WITH_AES_128_GCM_SHA256);
387 CIPHER(TLS_DHE_PSK_WITH_AES_256_GCM_SHA384);
388 CIPHER(TLS_RSA_PSK_WITH_AES_128_GCM_SHA256);
389 CIPHER(TLS_RSA_PSK_WITH_AES_256_GCM_SHA384);
390 CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA256);
391 CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA384);
392 CIPHER(TLS_PSK_WITH_NULL_SHA256);
393 CIPHER(TLS_PSK_WITH_NULL_SHA384);
394 CIPHER(TLS_DHE_PSK_WITH_AES_128_CBC_SHA256);
395 CIPHER(TLS_DHE_PSK_WITH_AES_256_CBC_SHA384);
396 CIPHER(TLS_DHE_PSK_WITH_NULL_SHA256);
397 CIPHER(TLS_DHE_PSK_WITH_NULL_SHA384);
398 CIPHER(TLS_RSA_PSK_WITH_AES_128_CBC_SHA256);
399 CIPHER(TLS_RSA_PSK_WITH_AES_256_CBC_SHA384);
400 CIPHER(TLS_RSA_PSK_WITH_NULL_SHA256);
401 CIPHER(TLS_RSA_PSK_WITH_NULL_SHA384);
402 CIPHER(TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
403 CIPHER(TLS_ECDH_ECDSA_WITH_NULL_SHA);
404 CIPHER(TLS_ECDH_ECDSA_WITH_RC4_128_SHA);
405 CIPHER(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA);
406 CIPHER(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA);
407 CIPHER(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA);
408 CIPHER(TLS_ECDHE_ECDSA_WITH_NULL_SHA);
409 CIPHER(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA);
410 CIPHER(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA);
411 CIPHER(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
412 CIPHER(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
413 CIPHER(TLS_ECDH_RSA_WITH_NULL_SHA);
414 CIPHER(TLS_ECDH_RSA_WITH_RC4_128_SHA);
415 CIPHER(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA);
416 CIPHER(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA);
417 CIPHER(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA);
418 CIPHER(TLS_ECDHE_RSA_WITH_NULL_SHA);
419 CIPHER(TLS_ECDHE_RSA_WITH_RC4_128_SHA);
420 CIPHER(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA);
421 CIPHER(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
422 CIPHER(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
423 CIPHER(TLS_ECDH_anon_WITH_NULL_SHA);
424 CIPHER(TLS_ECDH_anon_WITH_RC4_128_SHA);
425 CIPHER(TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA);
426 CIPHER(TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
427 CIPHER(TLS_ECDH_anon_WITH_AES_256_CBC_SHA);
428 CIPHER(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256);
429 CIPHER(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384);
430 CIPHER(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256);
431 CIPHER(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384);
432 CIPHER(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256);
433 CIPHER(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384);
434 CIPHER(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256);
435 CIPHER(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384);
436 CIPHER(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256);
437 CIPHER(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384);
438 CIPHER(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256);
439 CIPHER(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384);
440 CIPHER(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);
441 CIPHER(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
442 CIPHER(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256);
443 CIPHER(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384);
444 CIPHER(SSL_RSA_WITH_RC2_CBC_MD5);
445 CIPHER(SSL_RSA_WITH_IDEA_CBC_MD5);
446 CIPHER(SSL_RSA_WITH_DES_CBC_MD5);
447 CIPHER(SSL_RSA_WITH_3DES_EDE_CBC_MD5);
448 #undef CIPHER
450 return "TLS_NULL_WITH_NULL_NULL";
453 /* This code was borrowed from nss.c, with some modifications:
454 * Determine whether the nickname passed in is a filename that needs to
455 * be loaded as a PEM or a regular NSS nickname.
457 * returns 1 for a file
458 * returns 0 for not a file
460 CF_INLINE bool is_file(const char *filename)
462 struct_stat st;
464 if(filename == NULL)
465 return false;
467 if(stat(filename, &st) == 0)
468 return S_ISREG(st.st_mode);
469 return false;
472 /* Flags:
473 * 0x01 => show alt names for cert 0 if any
474 * 0x02 => show auth key id for last cert if any
475 * 0x20 => show even if empty (certs has 0 elements)
476 * 0x80 => suppress dates display
478 static void show_certs_array(struct SessionHandle *data, const char *hdr,
479 CFArrayRef certs, unsigned flags,
480 CSSM_TP_APPLE_EVIDENCE_INFO *evdnc)
482 CFIndex i, count = certs ? CFArrayGetCount(certs) : 0;
484 if(!hdr)
485 hdr = "Certificate list";
486 if(count || (flags &0x20)) {
487 infof(data, "---\n");
488 infof(data, "%s\n", hdr);
490 for(i = 0; i < count; ++i) {
491 SecCertificateRef copy = NULL;
492 char *subj, *subjalt=NULL, *issuer, *issuerkey=NULL, *na=NULL, *nb=NULL;
493 SecCertificateRef cert =
494 (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
495 if(SecIdentityGetTypeID() == CFGetTypeID(cert)) {
496 OSStatus err = SecIdentityCopyCertificate((SecIdentityRef)cert, &copy);
497 if(err)
498 continue;
499 cert = copy;
501 if(!(flags & 0x80)) {
502 CFStringRef cfnb, cfna;
503 CopyCertValidity(cert, &cfnb, &cfna);
504 nb = CFStringCreateUTF8String(cfnb, true);
505 na = CFStringCreateUTF8String(cfna, true);
507 subj = CFStringCreateUTF8String(CopyCertSubject(cert), true);
508 issuer = CFStringCreateUTF8String(CopyCertIssuer(cert), true);
509 infof(data, "%s%u s:%s\n",
510 ((evdnc && !(evdnc[i].StatusBits & CSSM_CERT_STATUS_IS_IN_INPUT_CERTS))
511 ? "+" : " "), (unsigned)i, subj ? subj : "<n/a>");
512 if(nb && na)
513 infof(data, " d:%s,%s\n", nb, na);
514 if(!i && (flags & 0x01))
515 subjalt = CFStringCreateUTF8String(
516 CopyCertSubjectAltNamesString(cert), true);
517 if(subjalt)
518 infof(data, " a:%s\n", subjalt);
519 infof(data, " i:%s\n", issuer ? issuer : "<n/a>");
520 if((flags & 0x02) && i+1 == count &&
521 (!subj || !issuer || strcmp(subj, issuer)))
522 issuerkey = CFStringCreateUTF8String(CopyCertIssuerKeyId(cert), true);
523 if(issuerkey)
524 infof(data, " k:%s\n", issuerkey);
525 free(nb);
526 free(na);
527 free(subj);
528 free(subjalt);
529 free(issuer);
530 free(issuerkey);
531 if(copy)
532 CFRelease(copy);
534 if(count || (flags &0x20)) {
535 infof(data, "---\n");
539 static void cleanup_mem(struct ssl_connect_data *connssl)
541 if(connssl->kh) {
542 DisposeIdentityKeychainHandle(connssl->kh);
543 connssl->kh = NULL;
545 if(connssl->ra) {
546 CFRelease((CFTypeRef)connssl->ra);
547 connssl->ra = NULL;
549 if(connssl->pa) {
550 CFRelease((CFTypeRef)connssl->pa);
551 connssl->pa = NULL;
555 static CURLcode darwinssl_connect_step1(struct connectdata *conn,
556 int sockindex)
558 struct SessionHandle *data = conn->data;
559 curl_socket_t sockfd = conn->sock[sockindex];
560 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
561 size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
562 SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
563 char *ssl_sessionid;
564 size_t ssl_sessionid_len;
565 OSStatus err = noErr;
567 cleanup_mem(connssl);
568 if(connssl->ssl_ctx)
569 cSSLDisposeContext(connssl->ssl_ctx);
570 connssl->ssl_ctx = cSSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
571 if(!connssl->ssl_ctx) {
572 failf(data, "SSL: couldn't create a context!");
573 return CURLE_OUT_OF_MEMORY;
575 connssl->ssl_write_buffered_length = 0UL; /* reset buffered write length */
577 /* check to see if we've been told to use an explicit SSL/TLS version */
578 switch(data->set.ssl.version) {
579 default:
580 case CURL_SSLVERSION_DEFAULT:
581 case CURL_SSLVERSION_TLSv1:
582 (void)cSSLSetProtocolVersionMinMax(connssl->ssl_ctx, kTLSProtocol1,
583 kTLSProtocol12);
584 break;
585 case CURL_SSLVERSION_TLSv1_0:
586 (void)cSSLSetProtocolVersionMinMax(connssl->ssl_ctx, kTLSProtocol1,
587 kTLSProtocol1);
588 break;
589 case CURL_SSLVERSION_TLSv1_1:
590 err = cSSLSetProtocolVersionMinMax(connssl->ssl_ctx, kTLSProtocol11,
591 kTLSProtocol11);
592 if(err != noErr) {
593 failf(data, "Your version of the OS does not support TLSv1.1");
594 return CURLE_SSL_CONNECT_ERROR;
596 break;
597 case CURL_SSLVERSION_TLSv1_2:
598 err = cSSLSetProtocolVersionMinMax(connssl->ssl_ctx, kTLSProtocol12,
599 kTLSProtocol12);
600 if(err != noErr) {
601 failf(data, "Your version of the OS does not support TLSv1.2");
602 return CURLE_SSL_CONNECT_ERROR;
604 break;
605 case CURL_SSLVERSION_SSLv3:
606 err = cSSLSetProtocolVersionMinMax(connssl->ssl_ctx, kSSLProtocol3,
607 kSSLProtocol3);
608 if(err != noErr) {
609 failf(data, "Your version of the OS does not support SSLv3");
610 return CURLE_SSL_CONNECT_ERROR;
612 break;
613 case CURL_SSLVERSION_SSLv2:
614 err = cSSLSetProtocolVersionMinMax(connssl->ssl_ctx, kSSLProtocol2,
615 kSSLProtocol2);
616 if(err != noErr) {
617 failf(data, "Your version of the OS does not support SSLv2");
618 return CURLE_SSL_CONNECT_ERROR;
620 break;
623 if(data->set.str[STRING_CERT]) {
624 CFArrayRef certs = NULL;
625 bool is_cert_file = is_file(data->set.str[STRING_CERT]);
627 /* User wants to authenticate with a client cert. Look for it:
628 If we detect that this is a file on disk, then let's load it.
629 Otherwise, assume that the user wants to use an identity loaded
630 from the Keychain. */
631 if(is_cert_file) {
632 errinfo_t e;
633 CFDataRef certdata;
634 CFDataRef keypw = NULL;
635 CFArrayRef clientauth;
636 const char *hintstr = NULL;
637 CFMutableStringRef hint = NULL;
638 e.f = (errinfo_func_t)failf;
639 e.u = data;
640 if(data->set.str[STRING_CERT_TYPE]) {
641 if(strcmp(data->set.str[STRING_CERT_TYPE], "DER") &&
642 strcmp(data->set.str[STRING_CERT_TYPE], "PEM")) {
643 failf(data, "not supported file type '%s' for certificate",
644 data->set.str[STRING_CERT_TYPE]);
645 return CURLE_SSL_CERTPROBLEM;
648 certdata = CFDataCreateWithContentsOfFile(NULL,
649 data->set.str[STRING_CERT]);
650 if(!certdata) {
651 failf(data, "unable to read certificate data file '%s'",
652 data->set.str[STRING_CERT]);
653 return CURLE_SSL_CERTPROBLEM;
655 hintstr = data->set.str[STRING_CERT];
656 certs = CreateCertsArrayWithData(certdata, &e);
657 if(!certs) {
658 CFRelease(certdata);
659 failf(data, "unable to load certificate data file '%s'",
660 data->set.str[STRING_CERT]);
661 return CURLE_SSL_CERTPROBLEM;
663 if(data->set.str[STRING_KEY]) {
664 CFRelease(certdata);
665 certdata = CFDataCreateWithContentsOfFile(NULL,
666 data->set.str[STRING_KEY]);
667 if(!certdata) {
668 CFRelease(certs);
669 failf(data, "unable to read certificate key file '%s'",
670 data->set.str[STRING_KEY]);
671 return CURLE_SSL_CERTPROBLEM;
673 hintstr = data->set.str[STRING_KEY];
675 if(data->set.str[STRING_KEY_PASSWD]) {
676 keypw = CFDataCreate(NULL, (UInt8 *)data->set.str[STRING_KEY_PASSWD],
677 strlen(data->set.str[STRING_KEY_PASSWD]));
679 if(hintstr) {
680 const char *base = strrchr(hintstr, '/');
681 if(base && base[1])
682 ++base;
683 else
684 base = hintstr;
685 hint = CFStringCreateMutable(kCFAllocatorDefault, 0);
686 if(hint) {
687 CFStringAppendCString(hint, "Enter password for private key ",
688 kCFStringEncodingUTF8);
689 CFStringAppendCString(hint, base, kCFStringEncodingUTF8);
692 if(connssl->kh) {
693 DisposeIdentityKeychainHandle(connssl->kh);
694 connssl->kh = NULL;
696 clientauth = CreateClientAuthWithCertificatesAndKeyData(certs, certdata,
697 keypw, hint, &connssl->kh);
698 CFRelease(certdata);
699 CFRelease(certs);
700 if(keypw)
701 CFRelease(keypw);
702 if(hint)
703 CFRelease(hint);
704 certs = clientauth;
705 if(!certs) {
706 failf(data, "unable to load certificate key (bad password or "
707 "cert/key mismatch?)");
708 return CURLE_SSL_CERTPROBLEM;
711 else {
712 SecIdentityRef cert_and_key = NULL;
713 CFTypeRef certs_c[1];
714 if(data->set.str[STRING_KEY]) {
715 infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure Trans"
716 "port when CURLOPT_SSLCERT is a Keychain item label.\n");
718 if(data->set.str[STRING_KEY_PASSWD]) {
719 infof(data, "WARNING: SSL: CURLOPT_SSLKEYPASSWD is ignored by Secure T"
720 "ransport when CURLOPT_SSLCERT is a Keychain item label.\n"
723 err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
724 if(err) {
725 switch(err) {
726 case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
727 failf(data, "SSL: Incorrect password for the certificate \"%s\" "
728 "and its private key.", data->set.str[STRING_CERT]);
729 break;
730 case -26275: /* errSecDecode */ case -25257:/* errSecUnknownFormat */
731 failf(data, "SSL: Couldn't make sense of the data in the "
732 "certificate \"%s\" and its private key.",
733 data->set.str[STRING_CERT]);
734 break;
735 case -25260: /* errSecPassphraseRequired */
736 failf(data, "SSL The certificate \"%s\" requires a password.",
737 data->set.str[STRING_CERT]);
738 break;
739 case errSecItemNotFound:
740 failf(data, "SSL: Can't find the certificate \"%s\" and its privat"
741 "e key in the Keychain.", data->set.str[STRING_CERT]);
742 break;
743 default:
744 failf(data, "SSL: Can't load the certificate \"%s\" and its privat"
745 "e key: OSStatus %d", data->set.str[STRING_CERT], err);
746 break;
748 return CURLE_SSL_CERTPROBLEM;
750 certs_c[0] = cert_and_key;
751 certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
752 &kCFTypeArrayCallBacks);
754 show_certs_array(data, "Client certificate(s)", certs, 0, NULL);
755 err = SSLSetCertificate(connssl->ssl_ctx, certs);
756 if(certs)
757 CFRelease(certs);
758 if(err != noErr) {
759 failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
760 return CURLE_SSL_CERTPROBLEM;
764 /* We don't depend on this setting working and on 10.6 even though the
765 * function is there it always returns unimpErr */
766 (void)cSSLSetSessionOption(connssl->ssl_ctx,
767 kSSLSessionOptionBreakOnServerAuth, true);
768 /* Later OS versions automatically disable cert verify when break on server
769 * auth is enabled, but we have to do it ourselves on earlier versions. */
770 err = SSLSetEnableCertVerify(connssl->ssl_ctx, false);
771 if(err != noErr) {
772 failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
773 return CURLE_SSL_CONNECT_ERROR;
775 if(data->set.ssl.verifypeer) {
776 /* The default anchors will be used unless SSLSetTrustedRoots is called
777 * with an array containing at least 1 element */
778 if(data->set.str[STRING_SSL_CAPATH]) {
779 failf(data, "SSL: CURLOPT_CAPATH is not supported by Secure Transport");
780 /* same error cURL would give without -Dhave_curlssl_ca_path */
781 return CURLE_NOT_BUILT_IN;
783 if(data->set.str[STRING_SSL_CAFILE]) {
784 errinfo_t e;
785 CFArrayRef cacerts;
786 CFDataRef cadata = CFDataCreateWithContentsOfFile(kCFAllocatorDefault,
787 data->set.str[STRING_SSL_CAFILE]);
789 if(!cadata) {
790 failf(data, "SSL: can't read CA certificate file %s",
791 data->set.str[STRING_SSL_CAFILE]);
792 return CURLE_SSL_CACERT_BADFILE;
794 e.f = (errinfo_func_t)failf;
795 e.u = data;
796 if(connssl->ra) {
797 CFRelease((CFTypeRef)connssl->ra);
798 connssl->ra = NULL;
800 cacerts = CreateCertsArrayWithData(cadata, &e);
801 CFRelease(cadata);
802 if(!cacerts) {
803 failf(data, "SSL: can't load CA certificate file %s",
804 data->set.str[STRING_SSL_CAFILE]);
805 return CURLE_SSL_CACERT_BADFILE;
807 connssl->ra = (void *)cacerts;
808 /* we will set these later on the trust before we evaluate so we don't
809 * require this to work here, but we try it anyway. */
810 err = cSSLSetTrustedRoots(connssl->ssl_ctx, cacerts, true);
811 if(err != noErr)
812 infof(data, "WARNING: SSL: SSLSetTrustedRoots() failed: OSStatus %d\n",
813 err);
816 else {
817 if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) {
818 infof(data, "WARNING: SSL: CA certificate(s) configured, but certificate"
819 " verification is disabled\n");
823 connssl->cf = 0;
824 #if LIBCURL_VERSION_NUM >= 0x072700
825 /* Collect public key pinning key(s). */
826 if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
827 errinfo_t e;
828 CFArrayRef pubkeys;
829 CFDataRef pindata;
831 e.f = (errinfo_func_t)failf;
832 e.u = data;
833 if(IsSha256HashList(data->set.str[STRING_SSL_PINNEDPUBLICKEY])) {
834 pubkeys = CreatePubKeySha256Array(
835 data->set.str[STRING_SSL_PINNEDPUBLICKEY], &e);
836 if(!pubkeys) {
837 failf(data, "SSL: can't parse pinned public key hashes %s",
838 data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
839 return CURLE_READ_ERROR;
841 connssl->cf |= 0x08;
843 else {
844 pindata = CFDataCreateWithContentsOfFile(kCFAllocatorDefault,
845 data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
846 if(!pindata) {
847 failf(data, "SSL: can't read pinned public key file %s",
848 data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
849 return CURLE_READ_ERROR;
851 pubkeys = CreatePubKeyArrayWithData(pindata, &e);
852 CFRelease(pindata);
853 if(!pubkeys) {
854 failf(data, "SSL: can't load pinned public key file %s",
855 data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
856 return CURLE_SSL_CACERT_BADFILE; /* no really good choice here */
859 if(connssl->pa) {
860 CFRelease((CFTypeRef)connssl->pa);
861 connssl->pa = NULL;
863 connssl->pa = (void *)pubkeys;
865 #endif
867 /* Configure hostname for SNI.
868 * SNI requires SSLSetPeerDomainName().
869 * RFC 6066 section 3 forbids IPv4 and IPv6 literal addresses in SNI.
871 connssl->vh = data->set.ssl.verifyhost ? true : false;
872 if(conn->host.name && conn->host.name[0] && !strchr(conn->host.name, ':')) {
873 size_t hnl = strlen(conn->host.name);
875 if(!IsIPv4Name(conn->host.name, hnl)) {
876 if(data->set.ssl.verifypeer)
877 connssl->vh = true;
878 err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
879 strlen(conn->host.name));
881 if(err != noErr) {
882 infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d"
883 "\n", err);
888 /* Disable cipher suites that ST supports but are not safe. These ciphers
889 are unlikely to be used in any case since ST gives other ciphers a much
890 higher priority, but it's probably better that we not connect at all than
891 to give the user a false sense of security if the server only supports
892 insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
893 (void)SSLGetNumberSupportedCiphers(connssl->ssl_ctx, &all_ciphers_count);
894 all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
895 allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
896 if(all_ciphers && allowed_ciphers &&
897 SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers,
898 &all_ciphers_count) == noErr) {
899 for(i = 0UL ; i < all_ciphers_count ; i++) {
900 /* There's a known bug in early versions of Mountain Lion where ST's ECC
901 ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
902 Work around the problem here by disabling those ciphers if we are
903 running in an affected version of OS X. */
904 if(kCFCoreFoundationVersionNumber>=kCFCoreFoundationVersionNumber10_8 &&
905 kCFCoreFoundationVersionNumber<=kCFCoreFoundationVersionNumber10_8_3
906 && all_ciphers[i] >= TLS_ECDH_ECDSA_WITH_NULL_SHA
907 && all_ciphers[i] <= TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) {
908 continue;
910 switch(all_ciphers[i]) {
911 /* Disable NULL ciphersuites: */
912 case SSL_NULL_WITH_NULL_NULL:
913 case SSL_RSA_WITH_NULL_MD5:
914 case SSL_RSA_WITH_NULL_SHA:
915 case TLS_RSA_WITH_NULL_SHA256:
916 case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
917 case TLS_ECDH_ECDSA_WITH_NULL_SHA:
918 case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
919 case TLS_ECDH_RSA_WITH_NULL_SHA:
920 case TLS_ECDHE_RSA_WITH_NULL_SHA:
921 case TLS_PSK_WITH_NULL_SHA:
922 case TLS_DHE_PSK_WITH_NULL_SHA:
923 case TLS_RSA_PSK_WITH_NULL_SHA:
924 case TLS_PSK_WITH_NULL_SHA256:
925 case TLS_PSK_WITH_NULL_SHA384:
926 case TLS_DHE_PSK_WITH_NULL_SHA256:
927 case TLS_DHE_PSK_WITH_NULL_SHA384:
928 case TLS_RSA_PSK_WITH_NULL_SHA256:
929 case TLS_RSA_PSK_WITH_NULL_SHA384:
930 /* Disable anonymous ciphersuites: */
931 case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
932 case SSL_DH_anon_WITH_RC4_128_MD5:
933 case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
934 case SSL_DH_anon_WITH_DES_CBC_SHA:
935 case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
936 case TLS_DH_anon_WITH_AES_128_CBC_SHA:
937 case TLS_DH_anon_WITH_AES_256_CBC_SHA:
938 case TLS_ECDH_anon_WITH_NULL_SHA:
939 case TLS_ECDH_anon_WITH_RC4_128_SHA:
940 case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
941 case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
942 case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
943 case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
944 case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
945 case TLS_DH_anon_WITH_AES_128_GCM_SHA256:
946 case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
947 /* Disable weak key ciphersuites: */
948 case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
949 case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
950 case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
951 case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
952 case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
953 case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
954 case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
955 case SSL_RSA_WITH_DES_CBC_SHA:
956 case SSL_DH_DSS_WITH_DES_CBC_SHA:
957 case SSL_DH_RSA_WITH_DES_CBC_SHA:
958 case SSL_DHE_DSS_WITH_DES_CBC_SHA:
959 case SSL_DHE_RSA_WITH_DES_CBC_SHA:
960 /* Disable IDEA: */
961 case SSL_RSA_WITH_IDEA_CBC_SHA:
962 case SSL_RSA_WITH_IDEA_CBC_MD5:
963 break;
964 default: /* enable everything else */
965 allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
966 break;
969 err = SSLSetEnabledCiphers(connssl->ssl_ctx, allowed_ciphers,
970 allowed_ciphers_count);
971 if(err != noErr) {
972 failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
973 return CURLE_SSL_CONNECT_ERROR;
976 else {
977 Curl_safefree(all_ciphers);
978 Curl_safefree(allowed_ciphers);
979 failf(data, "SSL: Failed to allocate memory for allowed ciphers");
980 return CURLE_OUT_OF_MEMORY;
982 Curl_safefree(all_ciphers);
983 Curl_safefree(allowed_ciphers);
985 if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber10_9) {
986 /* We want to enable 1/n-1 when using a CBC cipher unless the user
987 specifically doesn't want us doing that: */
988 cSSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
989 !data->set.ssl_enable_beast);
990 #if LIBCURL_VERSION_NUM >= 0x072a00
991 cSSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart,
992 data->set.ssl.falsestart); /* false start support */
993 #endif
996 /* Check if there's a cached ID we can/should use here! */
997 if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
998 &ssl_sessionid_len)) {
999 /* we got a session id, use it! */
1000 err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
1001 if(err != noErr) {
1002 failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
1003 return CURLE_SSL_CONNECT_ERROR;
1005 /* Informational message */
1006 infof(data, "SSL re-using session ID\n");
1008 /* If there isn't one, then let's make one up! This has to be done prior
1009 to starting the handshake. */
1010 else {
1011 CURLcode result;
1012 #if LIBCURL_VERSION_NUM >= 0x072700
1013 #define PKSTR data->set.str[STRING_SSL_PINNEDPUBLICKEY]
1014 #else
1015 #define PKSTR NULL
1016 #endif
1017 #define NSTR(s) ((s)?(s):"")
1018 ssl_sessionid =
1019 aprintf("%s:%s:%s:%d:%d:%s:%hu", NSTR(data->set.str[STRING_SSL_CAFILE]),
1020 NSTR(PKSTR), NSTR(data->set.str[STRING_CERT]),
1021 data->set.ssl.verifypeer, data->set.ssl.verifyhost,
1022 NSTR(conn->host.name), (unsigned short)conn->remote_port);
1023 ssl_sessionid_len = strlen(ssl_sessionid);
1024 #undef NSTR
1025 #undef PKSTR
1027 err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
1028 if(err != noErr) {
1029 failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
1030 return CURLE_SSL_CONNECT_ERROR;
1033 result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len);
1034 if(result) {
1035 failf(data, "failed to store ssl session");
1036 return result;
1040 err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
1041 if(err != noErr) {
1042 failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
1043 return CURLE_SSL_CONNECT_ERROR;
1046 /* pass the raw socket into the SSL layers */
1047 /* We need to store the FD in a constant memory address, because
1048 * SSLSetConnection() will not copy that address. I've found that
1049 * conn->sock[sockindex] may change on its own. */
1050 connssl->ssl_sockfd = sockfd;
1051 err = SSLSetConnection(connssl->ssl_ctx, connssl);
1052 if(err != noErr) {
1053 failf(data, "SSL: SSLSetConnection() failed: %d", err);
1054 return CURLE_SSL_CONNECT_ERROR;
1057 connssl->connecting_state = ssl_connect_2;
1058 return CURLE_OK;
1061 static bool
1062 is_ssl_ctx_connected(SSLContextRef ssl_ctx)
1064 SSLSessionState state = kSSLIdle;
1065 OSStatus err = SSLGetSessionState(ssl_ctx, &state);
1066 return !err && state == kSSLConnected;
1069 static CURLcode
1070 darwinssl_connect_step2(struct connectdata *conn, int sockindex)
1072 struct SessionHandle *data = conn->data;
1073 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1074 OSStatus err;
1075 SSLCipherSuite cipher;
1076 SSLProtocol protocol = 0;
1077 unsigned vflags = 0;
1079 DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
1080 || ssl_connect_2_reading == connssl->connecting_state
1081 || ssl_connect_2_writing == connssl->connecting_state);
1083 /* Here goes nothing: */
1084 err = SSLHandshake(connssl->ssl_ctx);
1086 /* set up the verify flags now */
1087 if(data->set.ssl.verifyhost && !data->set.ssl.verifypeer && conn->host.name
1088 && conn->host.name[0])
1089 vflags |= 0x04;
1090 if(connssl->pa && !data->set.ssl.verifypeer && !vflags)
1091 vflags |= 0x02;
1093 if(err == errSSLServerAuthCompleted) {
1094 if(data->set.ssl.verifypeer || vflags) {
1095 SecTrustRef trust = NULL;
1096 err = cSSLCopyPeerTrust(connssl->ssl_ctx, &trust);
1097 if(err) {
1098 failf(data, "SSL failed to retrieve SecTrust (%i)", (int)err);
1099 return CURLE_SSL_CONNECT_ERROR;
1101 err = VerifyTrustChain(trust, connssl->ra, connssl->cf|vflags, 0,
1102 connssl->vh ? conn->host.name : NULL, (CFArrayRef)connssl->pa);
1103 CFRelease(trust);
1105 else {
1106 err = noErr;
1108 if(err == noErr)
1109 /* the documentation says we need to call SSLHandshake() again */
1110 err = SSLHandshake(connssl->ssl_ctx);
1113 if(err == errSSLWouldBlock) { /* they're not done with us yet */
1114 connssl->connecting_state = connssl->ssl_direction ?
1115 ssl_connect_2_writing : ssl_connect_2_reading;
1116 return CURLE_OK;
1119 /* We may or may not have verified the peer yet if we have noErr depending
1120 * on whether or not we got errSSLServerAuthCompleted. So attempt to call
1121 * VerifyTrustChain again now (if it's already been evaluated there's minimal
1122 * work on subsequent calls) in that case. Always attempt to show the
1123 * computed certificate chain. */
1125 OSStatus err2;
1126 SecTrustRef trust = NULL;
1127 SecTrustResultType result;
1128 CSSM_TP_APPLE_EVIDENCE_INFO *evidence;
1129 CFArrayRef certChain = NULL;
1130 bool resumed;
1132 err2 = cSSLCopyPeerTrust(connssl->ssl_ctx, &trust);
1133 resumed = !err2 && !trust && is_ssl_ctx_connected(connssl->ssl_ctx);
1134 if(resumed) infof(data, "SSL successfully resumed session\n");
1135 if(!err && !resumed && (data->set.ssl.verifypeer || vflags)) {
1136 if(err2) {
1137 failf(data, "SSL failed to retrieve SecTrust (%i)", (int)err);
1138 return CURLE_SSL_CONNECT_ERROR;
1140 err = VerifyTrustChain(trust, connssl->ra, connssl->cf|vflags, 0,
1141 connssl->vh ? conn->host.name : NULL, (CFArrayRef)connssl->pa);
1144 /* Try to show the peer certificates unless we've connected successfully
1145 * and have verified the peer */
1146 if(err || !data->set.ssl.verifypeer) {
1147 CFArrayRef srv_certs;
1148 OSStatus err3 = cSSLCopyPeerCertificates(connssl->ssl_ctx, &srv_certs);
1150 if(!err3 && srv_certs)
1151 show_certs_array(data, "Server certificate(s)", srv_certs, 0x03, NULL);
1152 if(srv_certs)
1153 CFRelease(srv_certs);
1156 /* Try to show the computed certificate chain even on failure */
1157 if(!resumed && !err2)
1158 err2 = cSecTrustGetResult(trust, &result, &certChain, &evidence);
1159 if(!resumed && !err2)
1160 show_certs_array(data, (err || vflags) ?
1161 "Candidate/partial certificate chain" :
1162 "Certificate chain", certChain, 0x05, evidence);
1163 if(certChain)
1164 CFRelease(certChain);
1165 if(trust)
1166 CFRelease(trust);
1169 if(err != noErr) {
1170 switch (err) {
1171 case errSSLServerAuthCompleted:
1172 failf(data, "SSL unexpected errSSLServerAuthCompleted error in "
1173 "connection to %s", conn->host.name);
1174 return CURLE_SSL_CONNECT_ERROR;
1176 /* These are all certificate problems with the server: */
1177 case errSSLXCertChainInvalid:
1178 failf(data, "SSL certificate problem: Invalid certificate chain");
1179 return CURLE_SSL_CACERT;
1180 case errSSLUnknownRootCert:
1181 failf(data, "SSL certificate problem: Untrusted root certificate");
1182 return CURLE_SSL_CACERT;
1183 case errSSLNoRootCert:
1184 failf(data, "SSL certificate problem: No root certificate");
1185 return CURLE_SSL_CACERT;
1186 case errSSLCertExpired:
1187 failf(data, "SSL certificate problem: Certificate chain had an "
1188 "expired certificate");
1189 return CURLE_SSL_CACERT;
1190 case errSSLCertNotYetValid:
1191 failf(data, "SSL certificate problem: Certificate chain had a "
1192 "not yet valid certificate");
1193 return CURLE_SSL_CACERT;
1194 case errSSLBadCert:
1195 failf(data, "SSL certificate problem: Couldn't understand the server "
1196 "certificate format");
1197 return CURLE_SSL_CONNECT_ERROR;
1199 /* These are all certificate problems with the client: */
1200 case errSecTrustSettingDeny:
1201 failf(data, "SSL authentication failed trust setting is set to deny");
1202 return CURLE_SSL_CONNECT_ERROR;
1203 case errSecNotTrusted: /* some reason other than denied */
1204 failf(data, "SSL authentication failed");
1205 return CURLE_SSL_CONNECT_ERROR;
1206 case errSecAuthFailed:
1207 failf(data, "SSL authentication failed");
1208 return CURLE_SSL_CONNECT_ERROR;
1209 case errSSLPeerHandshakeFail:
1210 failf(data, "SSL peer handshake failed, the server most likely "
1211 "requires a client certificate to connect");
1212 return CURLE_SSL_CONNECT_ERROR;
1213 case errSSLPeerUnknownCA:
1214 failf(data, "SSL server rejected the client certificate due to "
1215 "the certificate being signed by an unknown certificate "
1216 "authority");
1217 return CURLE_SSL_CONNECT_ERROR;
1218 case errSecNoSuchKeychain:
1219 failf(data, "Client could not find the key's Keychain during the SSL "
1220 "handshake attempt to authenticate the client");
1221 return CURLE_SSL_CONNECT_ERROR;
1223 /* This error is raised if the server's cert didn't match the server's
1224 host name: */
1225 case errSSLHostNameMismatch:
1226 failf(data, "SSL certificate peer verification failed, the server's "
1227 "certificate did not match \"%s\"", conn->host.dispname);
1228 return CURLE_PEER_FAILED_VERIFICATION;
1230 #if LIBCURL_VERSION_NUM >= 0x072700
1231 /* This error is raised if public key pinning is enabled and the
1232 server certificate's public key does not match: */
1233 case errSecPinnedKeyMismatch:
1234 failf(data, "SSL certificate public key does not match pinned public "
1235 "key(s)");
1236 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1237 #endif
1239 /* Generic handshake errors: */
1240 case errSSLConnectionRefused:
1241 failf(data, "Server dropped the connection during the SSL handshake");
1242 return CURLE_SSL_CONNECT_ERROR;
1243 case errSSLClosedAbort:
1244 failf(data, "Server aborted the SSL handshake");
1245 return CURLE_SSL_CONNECT_ERROR;
1246 case errSSLNegotiation:
1247 failf(data, "Could not negotiate an SSL cipher suite with the server");
1248 return CURLE_SSL_CONNECT_ERROR;
1249 /* Sometimes paramErr happens with buggy ciphers: */
1250 case paramErr: case errSSLInternal:
1251 failf(data, "Internal SSL engine error encountered during the "
1252 "SSL handshake");
1253 return CURLE_SSL_CONNECT_ERROR;
1254 case errSSLFatalAlert:
1255 failf(data, "Fatal SSL engine error encountered during the SSL "
1256 "handshake");
1257 return CURLE_SSL_CONNECT_ERROR;
1258 default:
1259 failf(data, "Unknown SSL protocol error in connection to %s: %d",
1260 conn->host.name, err);
1261 return CURLE_SSL_CONNECT_ERROR;
1264 else {
1265 /* we have been connected fine, we're not waiting for anything else. */
1266 connssl->connecting_state = ssl_connect_3;
1268 /* this could possibly negatively affect renegotiation, however, we're
1269 * not prepared to handle any subsequent errSSLServerAuthCompleted errors
1270 * anyway so it's probably broken already. */
1271 /* remove any temporary files now */
1272 cleanup_mem(connssl);
1274 /* Informational message */
1275 (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
1276 (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
1277 switch (protocol) {
1278 case kSSLProtocol2:
1279 infof(data, "SSL 2.0 connection using %s\n",
1280 SSLCipherNameForNumber(cipher));
1281 break;
1282 case kSSLProtocol3:
1283 infof(data, "SSL 3.0 connection using %s\n",
1284 SSLCipherNameForNumber(cipher));
1285 break;
1286 case kTLSProtocol1:
1287 infof(data, "TLS 1.0 connection using %s\n",
1288 TLSCipherNameForNumber(cipher));
1289 break;
1290 case kTLSProtocol11:
1291 infof(data, "TLS 1.1 connection using %s\n",
1292 TLSCipherNameForNumber(cipher));
1293 break;
1294 case kTLSProtocol12:
1295 infof(data, "TLS 1.2 connection using %s\n",
1296 TLSCipherNameForNumber(cipher));
1297 break;
1298 default:
1299 infof(data, "Unknown protocol connection\n");
1300 break;
1303 return CURLE_OK;
1307 static CURLcode
1308 darwinssl_connect_step3(struct connectdata *conn,
1309 int sockindex)
1311 /*struct SessionHandle *data = conn->data;*/
1312 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1314 /* There is no step 3! */
1315 connssl->connecting_state = ssl_connect_done;
1316 return CURLE_OK;
1319 static Curl_recv darwinssl_recv;
1320 static Curl_send darwinssl_send;
1322 static CURLcode
1323 darwinssl_connect_common(struct connectdata *conn,
1324 int sockindex,
1325 bool nonblocking,
1326 bool *done)
1328 CURLcode result;
1329 struct SessionHandle *data = conn->data;
1330 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1331 curl_socket_t sockfd = conn->sock[sockindex];
1332 long timeout_ms;
1333 int what;
1335 /* check if the connection has already been established */
1336 if(ssl_connection_complete == connssl->state) {
1337 *done = TRUE;
1338 return CURLE_OK;
1341 if(ssl_connect_1==connssl->connecting_state) {
1342 /* Find out how much more time we're allowed */
1343 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1345 if(timeout_ms < 0) {
1346 /* no need to continue if time already is up */
1347 failf(data, "SSL connection timeout");
1348 return CURLE_OPERATION_TIMEDOUT;
1351 result = darwinssl_connect_step1(conn, sockindex);
1352 if(result) {
1353 cleanup_mem(connssl);
1354 return result;
1358 while(ssl_connect_2 == connssl->connecting_state ||
1359 ssl_connect_2_reading == connssl->connecting_state ||
1360 ssl_connect_2_writing == connssl->connecting_state) {
1362 /* check allowed time left */
1363 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1365 if(timeout_ms < 0) {
1366 /* no need to continue if time already is up */
1367 failf(data, "SSL connection timeout");
1368 return CURLE_OPERATION_TIMEDOUT;
1371 /* if ssl is expecting something, check if it's available. */
1372 if(connssl->connecting_state == ssl_connect_2_reading ||
1373 connssl->connecting_state == ssl_connect_2_writing) {
1375 curl_socket_t writefd = ssl_connect_2_writing ==
1376 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
1377 curl_socket_t readfd = ssl_connect_2_reading ==
1378 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
1380 what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
1381 if(what < 0) {
1382 /* fatal error */
1383 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1384 return CURLE_SSL_CONNECT_ERROR;
1386 else if(0 == what) {
1387 if(nonblocking) {
1388 *done = FALSE;
1389 return CURLE_OK;
1391 else {
1392 /* timeout */
1393 failf(data, "SSL connection timeout");
1394 return CURLE_OPERATION_TIMEDOUT;
1397 /* socket is readable or writable */
1400 /* Run transaction, and return to the caller if it failed or if this
1401 * connection is done nonblocking and this loop would execute again. This
1402 * permits the owner of a multi handle to abort a connection attempt
1403 * before step2 has completed while ensuring that a client using select()
1404 * or epoll() will always have a valid fdset to wait on.
1406 result = darwinssl_connect_step2(conn, sockindex);
1407 if(result)
1408 cleanup_mem(connssl);
1409 if(result || (nonblocking &&
1410 (ssl_connect_2 == connssl->connecting_state ||
1411 ssl_connect_2_reading == connssl->connecting_state ||
1412 ssl_connect_2_writing == connssl->connecting_state)))
1413 return result;
1415 } /* repeat step2 until all transactions are done. */
1418 if(ssl_connect_3 == connssl->connecting_state) {
1419 result = darwinssl_connect_step3(conn, sockindex);
1420 if(result) {
1421 cleanup_mem(connssl);
1422 return result;
1426 if(ssl_connect_done == connssl->connecting_state) {
1427 connssl->state = ssl_connection_complete;
1428 conn->recv[sockindex] = darwinssl_recv;
1429 conn->send[sockindex] = darwinssl_send;
1430 *done = TRUE;
1432 else
1433 *done = FALSE;
1435 /* Reset our connect state machine */
1436 connssl->connecting_state = ssl_connect_1;
1438 return CURLE_OK;
1441 CURLcode
1442 Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
1443 int sockindex,
1444 bool *done)
1446 return darwinssl_connect_common(conn, sockindex, TRUE, done);
1449 CURLcode
1450 Curl_darwinssl_connect(struct connectdata *conn,
1451 int sockindex)
1453 CURLcode result;
1454 bool done = FALSE;
1456 result = darwinssl_connect_common(conn, sockindex, FALSE, &done);
1458 if(result)
1459 return result;
1461 DEBUGASSERT(done);
1463 return CURLE_OK;
1466 void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
1468 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1470 if(connssl->ssl_ctx) {
1471 (void)SSLClose(connssl->ssl_ctx);
1472 cSSLDisposeContext(connssl->ssl_ctx);
1473 connssl->ssl_ctx = NULL;
1475 connssl->ssl_sockfd = 0;
1476 cleanup_mem(connssl);
1479 void Curl_darwinssl_close_all(struct SessionHandle *data);
1480 void Curl_darwinssl_close_all(struct SessionHandle *data)
1482 /* SecureTransport doesn't separate sessions from contexts, so... */
1483 (void)data;
1486 int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
1488 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1489 struct SessionHandle *data = conn->data;
1490 ssize_t nread;
1491 int what;
1492 int rc;
1493 char buf[120];
1495 if(!connssl->ssl_ctx)
1496 return 0;
1498 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
1499 return 0;
1501 Curl_darwinssl_close(conn, sockindex);
1503 rc = 0;
1505 what = Curl_socket_ready(conn->sock[sockindex],
1506 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
1508 for(;;) {
1509 if(what < 0) {
1510 /* anything that gets here is fatally bad */
1511 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1512 rc = -1;
1513 break;
1516 if(!what) { /* timeout */
1517 failf(data, "SSL shutdown timeout");
1518 break;
1521 /* Something to read, let's do it and hope that it is the close
1522 notify alert from the server. No way to SSL_Read now, so use read(). */
1524 nread = read(conn->sock[sockindex], buf, sizeof(buf));
1526 if(nread < 0) {
1527 failf(data, "read: %s", strerror(errno));
1528 rc = -1;
1531 if(nread <= 0)
1532 break;
1534 what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
1537 return rc;
1540 void Curl_darwinssl_session_free(void *ptr)
1542 /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
1543 cached session ID inside the Security framework. There is a private
1544 function that does this, but I don't want to have to explain to you why I
1545 got your application rejected from the App Store due to the use of a
1546 private API, so the best we can do is free up our own char array that we
1547 created way back in darwinssl_connect_step1... */
1548 Curl_safefree(ptr);
1551 size_t Curl_darwinssl_version(char *buffer, size_t size)
1553 return snprintf(buffer, size, "SecureTransport");
1557 * This function uses SSLGetSessionState to determine connection status.
1559 * Return codes:
1560 * 1 means the connection is still in place
1561 * 0 means the connection has been closed
1562 * -1 means the connection status is unknown
1564 int Curl_darwinssl_check_cxn(struct connectdata *conn)
1566 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1567 OSStatus err;
1568 SSLSessionState state;
1570 if(connssl->ssl_ctx) {
1571 err = SSLGetSessionState(connssl->ssl_ctx, &state);
1572 if(err == noErr)
1573 return state == kSSLConnected || state == kSSLHandshake;
1574 return -1;
1576 return 0;
1579 bool Curl_darwinssl_data_pending(const struct connectdata *conn,
1580 int connindex)
1582 const struct ssl_connect_data *connssl = &conn->ssl[connindex];
1583 OSStatus err;
1584 size_t buffer;
1586 if(connssl->ssl_ctx) { /* SSL is in use */
1587 err = SSLGetBufferedReadSize(connssl->ssl_ctx, &buffer);
1588 if(err == noErr)
1589 return buffer > 0UL;
1590 return false;
1592 else
1593 return false;
1596 int Curl_darwinssl_random(unsigned char *entropy,
1597 size_t length)
1599 /* arc4random_buf() isn't available on cats older than Lion, so let's
1600 do this manually for the benefit of the older cats. */
1601 size_t i;
1602 u_int32_t random_number = 0;
1604 for(i = 0 ; i < length ; i++) {
1605 if(i % sizeof(u_int32_t) == 0)
1606 random_number = arc4random();
1607 entropy[i] = random_number & 0xFF;
1608 random_number >>= 8;
1610 i = random_number = 0;
1611 return 0;
1614 void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
1615 size_t tmplen,
1616 unsigned char *md5sum, /* output */
1617 size_t md5len);
1618 void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
1619 size_t tmplen,
1620 unsigned char *md5sum, /* output */
1621 size_t md5len)
1623 CC_MD5_CTX ctx;
1624 (void)md5len;
1625 (void)CC_MD5_Init(&ctx);
1626 (void)CC_MD5_Update(&ctx, tmp, (CC_LONG)tmplen);
1627 (void)CC_MD5_Final(md5sum, &ctx);
1630 bool Curl_darwinssl_false_start(void);
1631 bool Curl_darwinssl_false_start(void) {
1632 return kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber10_9;
1635 static ssize_t darwinssl_send(struct connectdata *conn,
1636 int sockindex,
1637 const void *mem,
1638 size_t len,
1639 CURLcode *curlcode)
1641 /*struct SessionHandle *data = conn->data;*/
1642 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1643 size_t processed = 0UL;
1644 OSStatus err;
1646 /* The SSLWrite() function works a little differently than expected. The
1647 fourth argument (processed) is currently documented in Apple's
1648 documentation as: "On return, the length, in bytes, of the data actually
1649 written."
1651 Now, one could interpret that as "written to the socket," but actually,
1652 it returns the amount of data that was written to a buffer internal to
1653 the SSLContextRef instead. So it's possible for SSLWrite() to return
1654 errSSLWouldBlock and a number of bytes "written" because those bytes were
1655 encrypted and written to a buffer, not to the socket.
1657 So if this happens, then we need to keep calling SSLWrite() over and
1658 over again with no new data until it quits returning errSSLWouldBlock. */
1660 /* Do we have buffered data to write from the last time we were called? */
1661 if(connssl->ssl_write_buffered_length) {
1662 /* Write the buffered data: */
1663 err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed);
1664 switch (err) {
1665 case noErr:
1666 /* processed is always going to be 0 because we didn't write to
1667 the buffer, so return how much was written to the socket */
1668 processed = connssl->ssl_write_buffered_length;
1669 connssl->ssl_write_buffered_length = 0UL;
1670 break;
1671 case errSSLWouldBlock: /* argh, try again */
1672 *curlcode = CURLE_AGAIN;
1673 return -1L;
1674 default:
1675 failf(conn->data, "SSLWrite() returned error %d", err);
1676 *curlcode = CURLE_SEND_ERROR;
1677 return -1L;
1680 else {
1681 /* We've got new data to write: */
1682 err = SSLWrite(connssl->ssl_ctx, mem, len, &processed);
1683 if(err != noErr) {
1684 switch (err) {
1685 case errSSLWouldBlock:
1686 /* Data was buffered but not sent, we have to tell the caller
1687 to try sending again, and remember how much was buffered */
1688 connssl->ssl_write_buffered_length = len;
1689 *curlcode = CURLE_AGAIN;
1690 return -1L;
1691 default:
1692 failf(conn->data, "SSLWrite() returned error %d", err);
1693 *curlcode = CURLE_SEND_ERROR;
1694 return -1L;
1698 return (ssize_t)processed;
1701 static ssize_t darwinssl_recv(struct connectdata *conn,
1702 int num,
1703 char *buf,
1704 size_t buffersize,
1705 CURLcode *curlcode)
1707 /*struct SessionHandle *data = conn->data;*/
1708 struct ssl_connect_data *connssl = &conn->ssl[num];
1709 size_t processed = 0UL;
1710 OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed);
1712 if(err != noErr) {
1713 switch (err) {
1714 case errSSLWouldBlock: /* return how much we read (if anything) */
1715 if(processed)
1716 return (ssize_t)processed;
1717 *curlcode = CURLE_AGAIN;
1718 return -1L;
1719 break;
1721 /* errSSLClosedGraceful - server gracefully shut down the SSL session
1722 errSSLClosedNoNotify - server hung up on us instead of sending a
1723 closure alert notice, read() is returning 0
1724 Either way, inform the caller that the server disconnected. */
1725 case errSSLClosedGraceful:
1726 case errSSLClosedNoNotify:
1727 *curlcode = CURLE_OK;
1728 return -1L;
1729 break;
1731 default:
1732 failf(conn->data, "SSLRead() return error %d", err);
1733 *curlcode = CURLE_RECV_ERROR;
1734 return -1L;
1735 break;
1738 return (ssize_t)processed;
1741 #include "stcompat.c"
1743 #endif /* USE_DARWINSSL */