1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404 |
- /***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
- /*
- * Source file for all iOS and Mac OS X SecureTransport-specific code for the
- * TLS/SSL layer. No code but vtls.c should ever call or use these functions.
- */
- #include "curl_setup.h"
- #include "urldata.h" /* for the SessionHandle definition */
- #include "curl_base64.h"
- #ifdef USE_DARWINSSL
- #ifdef HAVE_LIMITS_H
- #include <limits.h>
- #endif
- #include <Security/Security.h>
- #include <Security/SecureTransport.h>
- #include <CoreFoundation/CoreFoundation.h>
- #include <CommonCrypto/CommonDigest.h>
- /* The Security framework has changed greatly between iOS and different OS X
- versions, and we will try to support as many of them as we can (back to
- Leopard and iOS 5) by using macros and weak-linking.
- IMPORTANT: If TLS 1.1 and 1.2 support are important for you on OS X, then
- you must build this project against the 10.8 SDK or later. */
- #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
- #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
- #error "The darwinssl back-end requires Leopard or later."
- #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
- #define CURL_BUILD_IOS 0
- #define CURL_BUILD_IOS_7 0
- #define CURL_BUILD_MAC 1
- /* This is the maximum API level we are allowed to use when building: */
- #define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
- #define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
- #define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
- #define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
- #define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
- /* These macros mean "the following code is present to allow runtime backward
- compatibility with at least this cat or earlier":
- (You set this at build-time by setting the MACOSX_DEPLOYMENT_TARGET
- environmental variable.) */
- #define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
- #define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
- #define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
- #define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080
- #define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090
- #elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
- #define CURL_BUILD_IOS 1
- #define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
- #define CURL_BUILD_MAC 0
- #define CURL_BUILD_MAC_10_5 0
- #define CURL_BUILD_MAC_10_6 0
- #define CURL_BUILD_MAC_10_7 0
- #define CURL_BUILD_MAC_10_8 0
- #define CURL_SUPPORT_MAC_10_5 0
- #define CURL_SUPPORT_MAC_10_6 0
- #define CURL_SUPPORT_MAC_10_7 0
- #define CURL_SUPPORT_MAC_10_8 0
- #else
- #error "The darwinssl back-end requires iOS or OS X."
- #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
- #if CURL_BUILD_MAC
- #include <sys/sysctl.h>
- #endif /* CURL_BUILD_MAC */
- #include "urldata.h"
- #include "sendf.h"
- #include "inet_pton.h"
- #include "connect.h"
- #include "select.h"
- #include "vtls.h"
- #include "curl_darwinssl.h"
- #define _MPRINTF_REPLACE /* use our functions only */
- #include <curl/mprintf.h>
- #include "curl_memory.h"
- /* The last #include file should be: */
- #include "memdebug.h"
- /* From MacTypes.h (which we can't include because it isn't present in iOS: */
- #define ioErr -36
- #define paramErr -50
- /* The following two functions were ripped from Apple sample code,
- * with some modifications: */
- static OSStatus SocketRead(SSLConnectionRef connection,
- void *data, /* owned by
- * caller, data
- * RETURNED */
- size_t *dataLength) /* IN/OUT */
- {
- size_t bytesToGo = *dataLength;
- size_t initLen = bytesToGo;
- UInt8 *currData = (UInt8 *)data;
- /*int sock = *(int *)connection;*/
- struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
- int sock = connssl->ssl_sockfd;
- OSStatus rtn = noErr;
- size_t bytesRead;
- ssize_t rrtn;
- int theErr;
- *dataLength = 0;
- for(;;) {
- bytesRead = 0;
- rrtn = read(sock, currData, bytesToGo);
- if(rrtn <= 0) {
- /* this is guesswork... */
- theErr = errno;
- if(rrtn == 0) { /* EOF = server hung up */
- /* the framework will turn this into errSSLClosedNoNotify */
- rtn = errSSLClosedGraceful;
- }
- else /* do the switch */
- switch(theErr) {
- case ENOENT:
- /* connection closed */
- rtn = errSSLClosedGraceful;
- break;
- case ECONNRESET:
- rtn = errSSLClosedAbort;
- break;
- case EAGAIN:
- rtn = errSSLWouldBlock;
- connssl->ssl_direction = false;
- break;
- default:
- rtn = ioErr;
- break;
- }
- break;
- }
- else {
- bytesRead = rrtn;
- }
- bytesToGo -= bytesRead;
- currData += bytesRead;
- if(bytesToGo == 0) {
- /* filled buffer with incoming data, done */
- break;
- }
- }
- *dataLength = initLen - bytesToGo;
- return rtn;
- }
- static OSStatus SocketWrite(SSLConnectionRef connection,
- const void *data,
- size_t *dataLength) /* IN/OUT */
- {
- size_t bytesSent = 0;
- /*int sock = *(int *)connection;*/
- struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
- int sock = connssl->ssl_sockfd;
- ssize_t length;
- size_t dataLen = *dataLength;
- const UInt8 *dataPtr = (UInt8 *)data;
- OSStatus ortn;
- int theErr;
- *dataLength = 0;
- do {
- length = write(sock,
- (char*)dataPtr + bytesSent,
- dataLen - bytesSent);
- } while((length > 0) &&
- ( (bytesSent += length) < dataLen) );
- if(length <= 0) {
- theErr = errno;
- if(theErr == EAGAIN) {
- ortn = errSSLWouldBlock;
- connssl->ssl_direction = true;
- }
- else {
- ortn = ioErr;
- }
- }
- else {
- ortn = noErr;
- }
- *dataLength = bytesSent;
- return ortn;
- }
- CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
- switch (cipher) {
- /* SSL version 3.0 */
- case SSL_RSA_WITH_NULL_MD5:
- return "SSL_RSA_WITH_NULL_MD5";
- break;
- case SSL_RSA_WITH_NULL_SHA:
- return "SSL_RSA_WITH_NULL_SHA";
- break;
- case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
- return "SSL_RSA_EXPORT_WITH_RC4_40_MD5";
- break;
- case SSL_RSA_WITH_RC4_128_MD5:
- return "SSL_RSA_WITH_RC4_128_MD5";
- break;
- case SSL_RSA_WITH_RC4_128_SHA:
- return "SSL_RSA_WITH_RC4_128_SHA";
- break;
- case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
- return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
- break;
- case SSL_RSA_WITH_IDEA_CBC_SHA:
- return "SSL_RSA_WITH_IDEA_CBC_SHA";
- break;
- case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_RSA_WITH_DES_CBC_SHA:
- return "SSL_RSA_WITH_DES_CBC_SHA";
- break;
- case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
- return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_DH_DSS_WITH_DES_CBC_SHA:
- return "SSL_DH_DSS_WITH_DES_CBC_SHA";
- break;
- case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:
- return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_DH_RSA_WITH_DES_CBC_SHA:
- return "SSL_DH_RSA_WITH_DES_CBC_SHA";
- break;
- case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:
- return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_DHE_DSS_WITH_DES_CBC_SHA:
- return "SSL_DHE_DSS_WITH_DES_CBC_SHA";
- break;
- case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
- return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_DHE_RSA_WITH_DES_CBC_SHA:
- return "SSL_DHE_RSA_WITH_DES_CBC_SHA";
- break;
- case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
- return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
- return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5";
- break;
- case SSL_DH_anon_WITH_RC4_128_MD5:
- return "SSL_DH_anon_WITH_RC4_128_MD5";
- break;
- case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
- return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
- break;
- case SSL_DH_anon_WITH_DES_CBC_SHA:
- return "SSL_DH_anon_WITH_DES_CBC_SHA";
- break;
- case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
- return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
- return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
- break;
- case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
- return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
- break;
- /* TLS 1.0 with AES (RFC 3268)
- (Apparently these are used in SSLv3 implementations as well.) */
- case TLS_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
- return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
- return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_anon_WITH_AES_128_CBC_SHA:
- return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
- break;
- case TLS_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
- return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
- return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_anon_WITH_AES_256_CBC_SHA:
- return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
- break;
- /* SSL version 2.0 */
- case SSL_RSA_WITH_RC2_CBC_MD5:
- return "SSL_RSA_WITH_RC2_CBC_MD5";
- break;
- case SSL_RSA_WITH_IDEA_CBC_MD5:
- return "SSL_RSA_WITH_IDEA_CBC_MD5";
- break;
- case SSL_RSA_WITH_DES_CBC_MD5:
- return "SSL_RSA_WITH_DES_CBC_MD5";
- break;
- case SSL_RSA_WITH_3DES_EDE_CBC_MD5:
- return "SSL_RSA_WITH_3DES_EDE_CBC_MD5";
- break;
- }
- return "SSL_NULL_WITH_NULL_NULL";
- }
- CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
- switch(cipher) {
- /* TLS 1.0 with AES (RFC 3268) */
- case TLS_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
- return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
- return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DH_anon_WITH_AES_128_CBC_SHA:
- return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
- break;
- case TLS_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
- return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
- return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DH_anon_WITH_AES_256_CBC_SHA:
- return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
- break;
- #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
- /* TLS 1.0 with ECDSA (RFC 4492) */
- case TLS_ECDH_ECDSA_WITH_NULL_SHA:
- return "TLS_ECDH_ECDSA_WITH_NULL_SHA";
- break;
- case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
- return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
- break;
- case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
- return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
- return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
- return "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
- break;
- case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
- return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
- break;
- case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
- return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
- return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_ECDH_RSA_WITH_NULL_SHA:
- return "TLS_ECDH_RSA_WITH_NULL_SHA";
- break;
- case TLS_ECDH_RSA_WITH_RC4_128_SHA:
- return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
- break;
- case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_ECDHE_RSA_WITH_NULL_SHA:
- return "TLS_ECDHE_RSA_WITH_NULL_SHA";
- break;
- case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
- return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
- break;
- case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
- break;
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
- break;
- case TLS_ECDH_anon_WITH_NULL_SHA:
- return "TLS_ECDH_anon_WITH_NULL_SHA";
- break;
- case TLS_ECDH_anon_WITH_RC4_128_SHA:
- return "TLS_ECDH_anon_WITH_RC4_128_SHA";
- break;
- case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
- return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
- return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
- break;
- case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
- return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
- break;
- #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
- #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- /* TLS 1.2 (RFC 5246) */
- case TLS_RSA_WITH_NULL_MD5:
- return "TLS_RSA_WITH_NULL_MD5";
- break;
- case TLS_RSA_WITH_NULL_SHA:
- return "TLS_RSA_WITH_NULL_SHA";
- break;
- case TLS_RSA_WITH_RC4_128_MD5:
- return "TLS_RSA_WITH_RC4_128_MD5";
- break;
- case TLS_RSA_WITH_RC4_128_SHA:
- return "TLS_RSA_WITH_RC4_128_SHA";
- break;
- case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_RSA_WITH_NULL_SHA256:
- return "TLS_RSA_WITH_NULL_SHA256";
- break;
- case TLS_RSA_WITH_AES_128_CBC_SHA256:
- return "TLS_RSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_RSA_WITH_AES_256_CBC_SHA256:
- return "TLS_RSA_WITH_AES_256_CBC_SHA256";
- break;
- case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
- return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
- return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
- return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
- return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
- return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256";
- break;
- case TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
- return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256";
- break;
- case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
- return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256";
- break;
- case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
- return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
- break;
- case TLS_DH_anon_WITH_RC4_128_MD5:
- return "TLS_DH_anon_WITH_RC4_128_MD5";
- break;
- case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
- return "TLS_DH_anon_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
- return "TLS_DH_anon_WITH_AES_256_CBC_SHA256";
- break;
- /* TLS 1.2 with AES GCM (RFC 5288) */
- case TLS_RSA_WITH_AES_128_GCM_SHA256:
- return "TLS_RSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_RSA_WITH_AES_256_GCM_SHA384:
- return "TLS_RSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
- return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
- return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
- return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
- return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
- return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
- return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
- return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
- return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DH_anon_WITH_AES_128_GCM_SHA256:
- return "TLS_DH_anon_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
- return "TLS_DH_anon_WITH_AES_256_GCM_SHA384";
- break;
- /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
- return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
- return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
- return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
- return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
- return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
- return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
- return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
- return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
- return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
- return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
- return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
- return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_EMPTY_RENEGOTIATION_INFO_SCSV:
- return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
- break;
- #else
- case SSL_RSA_WITH_NULL_MD5:
- return "TLS_RSA_WITH_NULL_MD5";
- break;
- case SSL_RSA_WITH_NULL_SHA:
- return "TLS_RSA_WITH_NULL_SHA";
- break;
- case SSL_RSA_WITH_RC4_128_MD5:
- return "TLS_RSA_WITH_RC4_128_MD5";
- break;
- case SSL_RSA_WITH_RC4_128_SHA:
- return "TLS_RSA_WITH_RC4_128_SHA";
- break;
- case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
- return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
- break;
- case SSL_DH_anon_WITH_RC4_128_MD5:
- return "TLS_DH_anon_WITH_RC4_128_MD5";
- break;
- case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
- break;
- #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
- /* TLS PSK (RFC 4279): */
- case TLS_PSK_WITH_RC4_128_SHA:
- return "TLS_PSK_WITH_RC4_128_SHA";
- break;
- case TLS_PSK_WITH_3DES_EDE_CBC_SHA:
- return "TLS_PSK_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_PSK_WITH_AES_128_CBC_SHA:
- return "TLS_PSK_WITH_AES_128_CBC_SHA";
- break;
- case TLS_PSK_WITH_AES_256_CBC_SHA:
- return "TLS_PSK_WITH_AES_256_CBC_SHA";
- break;
- case TLS_DHE_PSK_WITH_RC4_128_SHA:
- return "TLS_DHE_PSK_WITH_RC4_128_SHA";
- break;
- case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
- return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
- return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA";
- break;
- case TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
- return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA";
- break;
- case TLS_RSA_PSK_WITH_RC4_128_SHA:
- return "TLS_RSA_PSK_WITH_RC4_128_SHA";
- break;
- case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
- return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA";
- break;
- case TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
- return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA";
- break;
- case TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
- return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA";
- break;
- /* More TLS PSK (RFC 4785): */
- case TLS_PSK_WITH_NULL_SHA:
- return "TLS_PSK_WITH_NULL_SHA";
- break;
- case TLS_DHE_PSK_WITH_NULL_SHA:
- return "TLS_DHE_PSK_WITH_NULL_SHA";
- break;
- case TLS_RSA_PSK_WITH_NULL_SHA:
- return "TLS_RSA_PSK_WITH_NULL_SHA";
- break;
- /* Even more TLS PSK (RFC 5487): */
- case TLS_PSK_WITH_AES_128_GCM_SHA256:
- return "TLS_PSK_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_PSK_WITH_AES_256_GCM_SHA384:
- return "TLS_PSK_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
- return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
- return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
- return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256";
- break;
- case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
- return "TLS_PSK_WITH_AES_256_GCM_SHA384";
- break;
- case TLS_PSK_WITH_AES_128_CBC_SHA256:
- return "TLS_PSK_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_PSK_WITH_AES_256_CBC_SHA384:
- return "TLS_PSK_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_PSK_WITH_NULL_SHA256:
- return "TLS_PSK_WITH_NULL_SHA256";
- break;
- case TLS_PSK_WITH_NULL_SHA384:
- return "TLS_PSK_WITH_NULL_SHA384";
- break;
- case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
- return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
- return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_DHE_PSK_WITH_NULL_SHA256:
- return "TLS_DHE_PSK_WITH_NULL_SHA256";
- break;
- case TLS_DHE_PSK_WITH_NULL_SHA384:
- return "TLS_RSA_PSK_WITH_NULL_SHA384";
- break;
- case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
- return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256";
- break;
- case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
- return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384";
- break;
- case TLS_RSA_PSK_WITH_NULL_SHA256:
- return "TLS_RSA_PSK_WITH_NULL_SHA256";
- break;
- case TLS_RSA_PSK_WITH_NULL_SHA384:
- return "TLS_RSA_PSK_WITH_NULL_SHA384";
- break;
- #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
- }
- return "TLS_NULL_WITH_NULL_NULL";
- }
- #if CURL_BUILD_MAC
- CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
- {
- int mib[2];
- char *os_version;
- size_t os_version_len;
- char *os_version_major, *os_version_minor/*, *os_version_point*/;
- /* Get the Darwin kernel version from the kernel using sysctl(): */
- mib[0] = CTL_KERN;
- mib[1] = KERN_OSRELEASE;
- if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1)
- return;
- os_version = malloc(os_version_len*sizeof(char));
- if(!os_version)
- return;
- if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) {
- free(os_version);
- return;
- }
- /* Parse the version: */
- os_version_major = strtok(os_version, ".");
- os_version_minor = strtok(NULL, ".");
- /*os_version_point = strtok(NULL, ".");*/
- *major = atoi(os_version_major);
- *minor = atoi(os_version_minor);
- free(os_version);
- }
- #endif /* CURL_BUILD_MAC */
- /* Apple provides a myriad of ways of getting information about a certificate
- into a string. Some aren't available under iOS or newer cats. So here's
- a unified function for getting a string describing the certificate that
- ought to work in all cats starting with Leopard. */
- CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
- {
- CFStringRef server_cert_summary = CFSTR("(null)");
- #if CURL_BUILD_IOS
- /* iOS: There's only one way to do this. */
- server_cert_summary = SecCertificateCopySubjectSummary(cert);
- #else
- #if CURL_BUILD_MAC_10_7
- /* Lion & later: Get the long description if we can. */
- if(SecCertificateCopyLongDescription != NULL)
- server_cert_summary =
- SecCertificateCopyLongDescription(NULL, cert, NULL);
- else
- #endif /* CURL_BUILD_MAC_10_7 */
- #if CURL_BUILD_MAC_10_6
- /* Snow Leopard: Get the certificate summary. */
- if(SecCertificateCopySubjectSummary != NULL)
- server_cert_summary = SecCertificateCopySubjectSummary(cert);
- else
- #endif /* CURL_BUILD_MAC_10_6 */
- /* Leopard is as far back as we go... */
- (void)SecCertificateCopyCommonName(cert, &server_cert_summary);
- #endif /* CURL_BUILD_IOS */
- return server_cert_summary;
- }
- #if CURL_SUPPORT_MAC_10_6
- /* The SecKeychainSearch API was deprecated in Lion, and using it will raise
- deprecation warnings, so let's not compile this unless it's necessary: */
- static OSStatus CopyIdentityWithLabelOldSchool(char *label,
- SecIdentityRef *out_c_a_k)
- {
- OSStatus status = errSecItemNotFound;
- SecKeychainAttributeList attr_list;
- SecKeychainAttribute attr;
- SecKeychainSearchRef search = NULL;
- SecCertificateRef cert = NULL;
- /* Set up the attribute list: */
- attr_list.count = 1L;
- attr_list.attr = &attr;
- /* Set up our lone search criterion: */
- attr.tag = kSecLabelItemAttr;
- attr.data = label;
- attr.length = (UInt32)strlen(label);
- /* Start searching: */
- status = SecKeychainSearchCreateFromAttributes(NULL,
- kSecCertificateItemClass,
- &attr_list,
- &search);
- if(status == noErr) {
- status = SecKeychainSearchCopyNext(search,
- (SecKeychainItemRef *)&cert);
- if(status == noErr && cert) {
- /* If we found a certificate, does it have a private key? */
- status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k);
- CFRelease(cert);
- }
- }
- if(search)
- CFRelease(search);
- return status;
- }
- #endif /* CURL_SUPPORT_MAC_10_6 */
- static OSStatus CopyIdentityWithLabel(char *label,
- SecIdentityRef *out_cert_and_key)
- {
- OSStatus status = errSecItemNotFound;
- #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
- /* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
- kSecClassIdentity was introduced in Lion. If both exist, let's use them
- to find the certificate. */
- if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) {
- CFTypeRef keys[4];
- CFTypeRef values[4];
- CFDictionaryRef query_dict;
- CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
- kCFStringEncodingUTF8);
- /* Set up our search criteria and expected results: */
- values[0] = kSecClassIdentity; /* we want a certificate and a key */
- keys[0] = kSecClass;
- values[1] = kCFBooleanTrue; /* we want a reference */
- keys[1] = kSecReturnRef;
- values[2] = kSecMatchLimitOne; /* one is enough, thanks */
- keys[2] = kSecMatchLimit;
- /* identity searches need a SecPolicyRef in order to work */
- values[3] = SecPolicyCreateSSL(false, label_cf);
- keys[3] = kSecMatchPolicy;
- query_dict = CFDictionaryCreate(NULL, (const void **)keys,
- (const void **)values, 4L,
- &kCFCopyStringDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFRelease(values[3]);
- CFRelease(label_cf);
- /* Do we have a match? */
- status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key);
- CFRelease(query_dict);
- }
- else {
- #if CURL_SUPPORT_MAC_10_6
- /* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
- status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
- #endif /* CURL_SUPPORT_MAC_10_7 */
- }
- #elif CURL_SUPPORT_MAC_10_6
- /* For developers building on older cats, we have no choice but to fall back
- to SecKeychainSearch. */
- status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
- #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
- return status;
- }
- static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
- const char *cPassword,
- SecIdentityRef *out_cert_and_key)
- {
- OSStatus status = errSecItemNotFound;
- CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation(NULL,
- (const UInt8 *)cPath, strlen(cPath), false);
- CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
- cPassword, kCFStringEncodingUTF8) : NULL;
- CFDataRef pkcs_data = NULL;
- /* We can import P12 files on iOS or OS X 10.7 or later: */
- /* These constants are documented as having first appeared in 10.6 but they
- raise linker errors when used on that cat for some reason. */
- #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
- if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
- NULL, NULL, &status)) {
- const void *cKeys[] = {kSecImportExportPassphrase};
- const void *cValues[] = {password};
- CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
- password ? 1L : 0L, NULL, NULL);
- CFArrayRef items = NULL;
- /* Here we go: */
- status = SecPKCS12Import(pkcs_data, options, &items);
- if(status == noErr && items && CFArrayGetCount(items)) {
- CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L);
- const void *temp_identity = CFDictionaryGetValue(identity_and_trust,
- kSecImportItemIdentity);
- /* Retain the identity; we don't care about any other data... */
- CFRetain(temp_identity);
- *out_cert_and_key = (SecIdentityRef)temp_identity;
- }
- if(items)
- CFRelease(items);
- CFRelease(options);
- CFRelease(pkcs_data);
- }
- #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
- if(password)
- CFRelease(password);
- CFRelease(pkcs_url);
- return status;
- }
- /* This code was borrowed from nss.c, with some modifications:
- * Determine whether the nickname passed in is a filename that needs to
- * be loaded as a PEM or a regular NSS nickname.
- *
- * returns 1 for a file
- * returns 0 for not a file
- */
- CF_INLINE bool is_file(const char *filename)
- {
- struct_stat st;
- if(filename == NULL)
- return false;
- if(stat(filename, &st) == 0)
- return S_ISREG(st.st_mode);
- return false;
- }
- static CURLcode darwinssl_connect_step1(struct connectdata *conn,
- int sockindex)
- {
- struct SessionHandle *data = conn->data;
- curl_socket_t sockfd = conn->sock[sockindex];
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- #ifdef ENABLE_IPV6
- struct in6_addr addr;
- #else
- struct in_addr addr;
- #endif /* ENABLE_IPV6 */
- size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
- SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
- char *ssl_sessionid;
- size_t ssl_sessionid_len;
- OSStatus err = noErr;
- #if CURL_BUILD_MAC
- int darwinver_maj = 0, darwinver_min = 0;
- GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
- #endif /* CURL_BUILD_MAC */
- #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- if(SSLCreateContext != NULL) { /* use the newer API if avaialble */
- if(connssl->ssl_ctx)
- CFRelease(connssl->ssl_ctx);
- connssl->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
- if(!connssl->ssl_ctx) {
- failf(data, "SSL: couldn't create a context!");
- return CURLE_OUT_OF_MEMORY;
- }
- }
- else {
- /* The old ST API does not exist under iOS, so don't compile it: */
- #if CURL_SUPPORT_MAC_10_8
- if(connssl->ssl_ctx)
- (void)SSLDisposeContext(connssl->ssl_ctx);
- err = SSLNewContext(false, &(connssl->ssl_ctx));
- if(err != noErr) {
- failf(data, "SSL: couldn't create a context: OSStatus %d", err);
- return CURLE_OUT_OF_MEMORY;
- }
- #endif /* CURL_SUPPORT_MAC_10_8 */
- }
- #else
- if(connssl->ssl_ctx)
- (void)SSLDisposeContext(connssl->ssl_ctx);
- err = SSLNewContext(false, &(connssl->ssl_ctx));
- if(err != noErr) {
- failf(data, "SSL: couldn't create a context: OSStatus %d", err);
- return CURLE_OUT_OF_MEMORY;
- }
- #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- connssl->ssl_write_buffered_length = 0UL; /* reset buffered write length */
- /* check to see if we've been told to use an explicit SSL/TLS version */
- #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- if(SSLSetProtocolVersionMax != NULL) {
- switch(data->set.ssl.version) {
- case CURL_SSLVERSION_DEFAULT: default:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
- break;
- case CURL_SSLVERSION_TLSv1:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
- break;
- case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
- break;
- case CURL_SSLVERSION_TLSv1_1:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11);
- break;
- case CURL_SSLVERSION_TLSv1_2:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
- break;
- case CURL_SSLVERSION_SSLv3:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
- break;
- case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
- }
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
- }
- }
- else {
- #if CURL_SUPPORT_MAC_10_8
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kSSLProtocolAll,
- false);
- switch (data->set.ssl.version) {
- case CURL_SSLVERSION_DEFAULT: default:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kSSLProtocol3,
- true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol1,
- true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol11,
- true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol12,
- true);
- break;
- case CURL_SSLVERSION_TLSv1:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol1,
- true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol11,
- true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol12,
- true);
- break;
- case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol1,
- true);
- break;
- case CURL_SSLVERSION_TLSv1_1:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol11,
- true);
- break;
- case CURL_SSLVERSION_TLSv1_2:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol12,
- true);
- break;
- case CURL_SSLVERSION_SSLv3:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kSSLProtocol3,
- true);
- break;
- case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kSSLProtocol2,
- true);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
- }
- break;
- }
- #endif /* CURL_SUPPORT_MAC_10_8 */
- }
- #else
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
- switch(data->set.ssl.version) {
- default:
- case CURL_SSLVERSION_DEFAULT:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kSSLProtocol3,
- true);
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol1,
- true);
- break;
- case CURL_SSLVERSION_TLSv1:
- case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol1,
- true);
- break;
- case CURL_SSLVERSION_TLSv1_1:
- failf(data, "Your version of the OS does not support TLSv1.1");
- return CURLE_SSL_CONNECT_ERROR;
- case CURL_SSLVERSION_TLSv1_2:
- failf(data, "Your version of the OS does not support TLSv1.2");
- return CURLE_SSL_CONNECT_ERROR;
- case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kSSLProtocol2,
- true);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
- }
- break;
- case CURL_SSLVERSION_SSLv3:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kSSLProtocol3,
- true);
- break;
- }
- #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- if(data->set.str[STRING_KEY]) {
- infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
- "Transport. The private key must be in the Keychain.\n");
- }
- if(data->set.str[STRING_CERT]) {
- SecIdentityRef cert_and_key = NULL;
- bool is_cert_file = is_file(data->set.str[STRING_CERT]);
- /* User wants to authenticate with a client cert. Look for it:
- If we detect that this is a file on disk, then let's load it.
- Otherwise, assume that the user wants to use an identity loaded
- from the Keychain. */
- if(is_cert_file) {
- if(!data->set.str[STRING_CERT_TYPE])
- infof(data, "WARNING: SSL: Certificate type not set, assuming "
- "PKCS#12 format.\n");
- else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12",
- strlen(data->set.str[STRING_CERT_TYPE])) != 0)
- infof(data, "WARNING: SSL: The Security framework only supports "
- "loading identities that are in PKCS#12 format.\n");
- err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT],
- data->set.str[STRING_KEY_PASSWD], &cert_and_key);
- }
- else
- err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
- if(err == noErr) {
- SecCertificateRef cert = NULL;
- CFTypeRef certs_c[1];
- CFArrayRef certs;
- /* If we found one, print it out: */
- err = SecIdentityCopyCertificate(cert_and_key, &cert);
- if(err == noErr) {
- CFStringRef cert_summary = CopyCertSubject(cert);
- char cert_summary_c[128];
- if(cert_summary) {
- memset(cert_summary_c, 0, 128);
- if(CFStringGetCString(cert_summary,
- cert_summary_c,
- 128,
- kCFStringEncodingUTF8)) {
- infof(data, "Client certificate: %s\n", cert_summary_c);
- }
- CFRelease(cert_summary);
- CFRelease(cert);
- }
- }
- certs_c[0] = cert_and_key;
- certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
- &kCFTypeArrayCallBacks);
- err = SSLSetCertificate(connssl->ssl_ctx, certs);
- if(certs)
- CFRelease(certs);
- if(err != noErr) {
- failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
- return CURLE_SSL_CERTPROBLEM;
- }
- CFRelease(cert_and_key);
- }
- else {
- switch(err) {
- case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
- failf(data, "SSL: Incorrect password for the certificate \"%s\" "
- "and its private key.", data->set.str[STRING_CERT]);
- break;
- case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
- failf(data, "SSL: Couldn't make sense of the data in the "
- "certificate \"%s\" and its private key.",
- data->set.str[STRING_CERT]);
- break;
- case -25260: /* errSecPassphraseRequired */
- failf(data, "SSL The certificate \"%s\" requires a password.",
- data->set.str[STRING_CERT]);
- break;
- case errSecItemNotFound:
- failf(data, "SSL: Can't find the certificate \"%s\" and its private "
- "key in the Keychain.", data->set.str[STRING_CERT]);
- break;
- default:
- failf(data, "SSL: Can't load the certificate \"%s\" and its private "
- "key: OSStatus %d", data->set.str[STRING_CERT], err);
- break;
- }
- return CURLE_SSL_CERTPROBLEM;
- }
- }
- /* SSL always tries to verify the peer, this only says whether it should
- * fail to connect if the verification fails, or if it should continue
- * anyway. In the latter case the result of the verification is checked with
- * SSL_get_verify_result() below. */
- #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
- /* Snow Leopard introduced the SSLSetSessionOption() function, but due to
- a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag
- works, it doesn't work as expected under Snow Leopard or Lion.
- So we need to call SSLSetEnableCertVerify() on those older cats in order
- to disable certificate validation if the user turned that off.
- (SecureTransport will always validate the certificate chain by
- default.) */
- /* (Note: Darwin 12.x.x is Mountain Lion.) */
- #if CURL_BUILD_MAC
- if(SSLSetSessionOption != NULL && darwinver_maj >= 12) {
- #else
- if(SSLSetSessionOption != NULL) {
- #endif /* CURL_BUILD_MAC */
- bool break_on_auth = !data->set.ssl.verifypeer ||
- data->set.str[STRING_SSL_CAFILE];
- err = SSLSetSessionOption(connssl->ssl_ctx,
- kSSLSessionOptionBreakOnServerAuth,
- break_on_auth);
- if(err != noErr) {
- failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
- else {
- #if CURL_SUPPORT_MAC_10_8
- err = SSLSetEnableCertVerify(connssl->ssl_ctx,
- data->set.ssl.verifypeer?true:false);
- if(err != noErr) {
- failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- #endif /* CURL_SUPPORT_MAC_10_8 */
- }
- #else
- err = SSLSetEnableCertVerify(connssl->ssl_ctx,
- data->set.ssl.verifypeer?true:false);
- if(err != noErr) {
- failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
- if(data->set.str[STRING_SSL_CAFILE]) {
- bool is_cert_file = is_file(data->set.str[STRING_SSL_CAFILE]);
- if(!is_cert_file) {
- failf(data, "SSL: can't load CA certificate file %s",
- data->set.str[STRING_SSL_CAFILE]);
- return CURLE_SSL_CACERT_BADFILE;
- }
- if(!data->set.ssl.verifypeer) {
- failf(data, "SSL: CA certificate set, but certificate verification "
- "is disabled");
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
- /* Configure hostname check. SNI is used if available.
- * Both hostname check and SNI require SSLSetPeerDomainName().
- * Also: the verifyhost setting influences SNI usage */
- if(data->set.ssl.verifyhost) {
- err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
- strlen(conn->host.name));
- if(err != noErr) {
- infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
- err);
- }
- if((Curl_inet_pton(AF_INET, conn->host.name, &addr))
- #ifdef ENABLE_IPV6
- || (Curl_inet_pton(AF_INET6, conn->host.name, &addr))
- #endif
- ) {
- infof(data, "WARNING: using IP address, SNI is being disabled by "
- "the OS.\n");
- }
- }
- /* Disable cipher suites that ST supports but are not safe. These ciphers
- are unlikely to be used in any case since ST gives other ciphers a much
- higher priority, but it's probably better that we not connect at all than
- to give the user a false sense of security if the server only supports
- insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
- (void)SSLGetNumberSupportedCiphers(connssl->ssl_ctx, &all_ciphers_count);
- all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
- allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
- if(all_ciphers && allowed_ciphers &&
- SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers,
- &all_ciphers_count) == noErr) {
- for(i = 0UL ; i < all_ciphers_count ; i++) {
- #if CURL_BUILD_MAC
- /* There's a known bug in early versions of Mountain Lion where ST's ECC
- ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
- Work around the problem here by disabling those ciphers if we are
- running in an affected version of OS X. */
- if(darwinver_maj == 12 && darwinver_min <= 3 &&
- all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
- continue;
- }
- #endif /* CURL_BUILD_MAC */
- switch(all_ciphers[i]) {
- /* Disable NULL ciphersuites: */
- case SSL_NULL_WITH_NULL_NULL:
- case SSL_RSA_WITH_NULL_MD5:
- case SSL_RSA_WITH_NULL_SHA:
- case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
- case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
- case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
- case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
- case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
- case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
- case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
- case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
- case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
- case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
- case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
- case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
- case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
- case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
- case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
- /* Disable anonymous ciphersuites: */
- case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
- case SSL_DH_anon_WITH_RC4_128_MD5:
- case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_anon_WITH_DES_CBC_SHA:
- case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
- case TLS_DH_anon_WITH_AES_128_CBC_SHA:
- case TLS_DH_anon_WITH_AES_256_CBC_SHA:
- case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */
- case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */
- case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */
- case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
- case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */
- case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */
- case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */
- case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */
- case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */
- /* Disable weak key ciphersuites: */
- case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
- case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
- case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_RSA_WITH_DES_CBC_SHA:
- case SSL_DH_DSS_WITH_DES_CBC_SHA:
- case SSL_DH_RSA_WITH_DES_CBC_SHA:
- case SSL_DHE_DSS_WITH_DES_CBC_SHA:
- case SSL_DHE_RSA_WITH_DES_CBC_SHA:
- /* Disable IDEA: */
- case SSL_RSA_WITH_IDEA_CBC_SHA:
- case SSL_RSA_WITH_IDEA_CBC_MD5:
- break;
- default: /* enable everything else */
- allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
- break;
- }
- }
- err = SSLSetEnabledCiphers(connssl->ssl_ctx, allowed_ciphers,
- allowed_ciphers_count);
- if(err != noErr) {
- failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
- else {
- Curl_safefree(all_ciphers);
- Curl_safefree(allowed_ciphers);
- failf(data, "SSL: Failed to allocate memory for allowed ciphers");
- return CURLE_OUT_OF_MEMORY;
- }
- Curl_safefree(all_ciphers);
- Curl_safefree(allowed_ciphers);
- #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
- /* We want to enable 1/n-1 when using a CBC cipher unless the user
- specifically doesn't want us doing that: */
- if(SSLSetSessionOption != NULL)
- SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
- !data->set.ssl_enable_beast);
- #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
- /* Check if there's a cached ID we can/should use here! */
- if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
- &ssl_sessionid_len)) {
- /* we got a session id, use it! */
- err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
- if(err != noErr) {
- failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- /* Informational message */
- infof(data, "SSL re-using session ID\n");
- }
- /* If there isn't one, then let's make one up! This has to be done prior
- to starting the handshake. */
- else {
- CURLcode retcode;
- ssl_sessionid = malloc(256*sizeof(char));
- ssl_sessionid_len = snprintf(ssl_sessionid, 256, "curl:%s:%hu",
- conn->host.name, conn->remote_port);
- err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
- if(err != noErr) {
- failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- retcode = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len);
- if(retcode!= CURLE_OK) {
- failf(data, "failed to store ssl session");
- return retcode;
- }
- }
- err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
- if(err != noErr) {
- failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- /* pass the raw socket into the SSL layers */
- /* We need to store the FD in a constant memory address, because
- * SSLSetConnection() will not copy that address. I've found that
- * conn->sock[sockindex] may change on its own. */
- connssl->ssl_sockfd = sockfd;
- err = SSLSetConnection(connssl->ssl_ctx, connssl);
- if(err != noErr) {
- failf(data, "SSL: SSLSetConnection() failed: %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- connssl->connecting_state = ssl_connect_2;
- return CURLE_OK;
- }
- static int pem_to_der(const char *in, unsigned char **out, size_t *outlen)
- {
- char *sep, *start, *end;
- size_t i, j, err;
- size_t len;
- unsigned char *b64;
- /* Jump through the separators in the first line. */
- sep = strstr(in, "-----");
- if(sep == NULL)
- return -1;
- sep = strstr(sep + 1, "-----");
- if(sep == NULL)
- return -1;
- start = sep + 5;
- /* Find beginning of last line separator. */
- end = strstr(start, "-----");
- if(end == NULL)
- return -1;
- len = end - start;
- *out = malloc(len);
- if(!*out)
- return -1;
- b64 = malloc(len + 1);
- if(!b64) {
- free(*out);
- return -1;
- }
- /* Create base64 string without linefeeds. */
- for(i = 0, j = 0; i < len; i++) {
- if(start[i] != '\r' && start[i] != '\n')
- b64[j++] = start[i];
- }
- b64[j] = '\0';
- err = Curl_base64_decode((const char *)b64, out, outlen);
- free(b64);
- if(err) {
- free(*out);
- return -1;
- }
- return 0;
- }
- static int read_cert(const char *file, unsigned char **out, size_t *outlen)
- {
- int fd;
- ssize_t n, len = 0, cap = 512;
- size_t derlen;
- unsigned char buf[cap], *data, *der;
- fd = open(file, 0);
- if(fd < 0)
- return -1;
- data = malloc(cap);
- if(!data) {
- close(fd);
- return -1;
- }
- for(;;) {
- n = read(fd, buf, sizeof(buf));
- if(n < 0) {
- close(fd);
- free(data);
- return -1;
- }
- else if(n == 0) {
- close(fd);
- break;
- }
- if(len + n >= cap) {
- cap *= 2;
- data = realloc(data, cap);
- if(!data) {
- close(fd);
- return -1;
- }
- }
- memcpy(data + len, buf, n);
- len += n;
- }
- data[len] = '\0';
- /*
- * Check if the certificate is in PEM format, and convert it to DER. If this
- * fails, we assume the certificate is in DER format.
- */
- if(pem_to_der((const char *)data, &der, &derlen) == 0) {
- free(data);
- data = der;
- len = derlen;
- }
- *out = data;
- *outlen = len;
- return 0;
- }
- static int sslerr_to_curlerr(struct SessionHandle *data, int err)
- {
- switch(err) {
- case errSSLXCertChainInvalid:
- failf(data, "SSL certificate problem: Invalid certificate chain");
- return CURLE_SSL_CACERT;
- case errSSLUnknownRootCert:
- failf(data, "SSL certificate problem: Untrusted root certificate");
- return CURLE_SSL_CACERT;
- case errSSLNoRootCert:
- failf(data, "SSL certificate problem: No root certificate");
- return CURLE_SSL_CACERT;
- case errSSLCertExpired:
- failf(data, "SSL certificate problem: Certificate chain had an "
- "expired certificate");
- return CURLE_SSL_CACERT;
- case errSSLBadCert:
- failf(data, "SSL certificate problem: Couldn't understand the server "
- "certificate format");
- return CURLE_SSL_CONNECT_ERROR;
- case errSSLHostNameMismatch:
- failf(data, "SSL certificate peer hostname mismatch");
- return CURLE_PEER_FAILED_VERIFICATION;
- default:
- failf(data, "SSL unexpected certificate error %d", err);
- return CURLE_SSL_CACERT;
- }
- }
- static int verify_cert(const char *cafile, struct SessionHandle *data,
- SSLContextRef ctx)
- {
- unsigned char *certbuf;
- size_t buflen;
- if(read_cert(cafile, &certbuf, &buflen) < 0) {
- failf(data, "SSL: failed to read or invalid CA certificate");
- return CURLE_SSL_CACERT;
- }
- CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, certbuf, buflen);
- free(certbuf);
- if(!certdata) {
- failf(data, "SSL: failed to allocate array for CA certificate");
- return CURLE_OUT_OF_MEMORY;
- }
- SecCertificateRef cacert = SecCertificateCreateWithData(kCFAllocatorDefault,
- certdata);
- CFRelease(certdata);
- if(!cacert) {
- failf(data, "SSL: failed to create SecCertificate from CA certificate");
- return CURLE_SSL_CACERT;
- }
- SecTrustRef trust;
- OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
- if(trust == NULL) {
- failf(data, "SSL: error getting certificate chain");
- return CURLE_OUT_OF_MEMORY;
- }
- else if(ret != noErr) {
- return sslerr_to_curlerr(data, ret);
- }
- CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks);
- CFArrayAppendValue(array, cacert);
- CFRelease(cacert);
- ret = SecTrustSetAnchorCertificates(trust, array);
- if(ret != noErr) {
- CFRelease(trust);
- return sslerr_to_curlerr(data, ret);
- }
- SecTrustResultType trust_eval = 0;
- ret = SecTrustEvaluate(trust, &trust_eval);
- CFRelease(array);
- CFRelease(trust);
- if(ret != noErr) {
- return sslerr_to_curlerr(data, ret);
- }
- switch (trust_eval) {
- case kSecTrustResultUnspecified:
- case kSecTrustResultProceed:
- infof(data, "SSL: certificate verification succeeded (result: %d)",
- trust_eval);
- return CURLE_OK;
- case kSecTrustResultRecoverableTrustFailure:
- case kSecTrustResultDeny:
- default:
- failf(data, "SSL: certificate verification failed (result: %d)",
- trust_eval);
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- }
- static CURLcode
- darwinssl_connect_step2(struct connectdata *conn, int sockindex)
- {
- struct SessionHandle *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- OSStatus err;
- SSLCipherSuite cipher;
- SSLProtocol protocol = 0;
- DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
- || ssl_connect_2_reading == connssl->connecting_state
- || ssl_connect_2_writing == connssl->connecting_state);
- /* Here goes nothing: */
- err = SSLHandshake(connssl->ssl_ctx);
- if(err != noErr) {
- switch (err) {
- case errSSLWouldBlock: /* they're not done with us yet */
- connssl->connecting_state = connssl->ssl_direction ?
- ssl_connect_2_writing : ssl_connect_2_reading;
- return CURLE_OK;
- /* The below is errSSLServerAuthCompleted; it's not defined in
- Leopard's headers */
- case -9841:
- if(data->set.str[STRING_SSL_CAFILE]) {
- int res = verify_cert(data->set.str[STRING_SSL_CAFILE], data,
- connssl->ssl_ctx);
- if(res != CURLE_OK)
- return res;
- }
- /* the documentation says we need to call SSLHandshake() again */
- return darwinssl_connect_step2(conn, sockindex);
- /* These are all certificate problems with the server: */
- case errSSLXCertChainInvalid:
- failf(data, "SSL certificate problem: Invalid certificate chain");
- return CURLE_SSL_CACERT;
- case errSSLUnknownRootCert:
- failf(data, "SSL certificate problem: Untrusted root certificate");
- return CURLE_SSL_CACERT;
- case errSSLNoRootCert:
- failf(data, "SSL certificate problem: No root certificate");
- return CURLE_SSL_CACERT;
- case errSSLCertExpired:
- failf(data, "SSL certificate problem: Certificate chain had an "
- "expired certificate");
- return CURLE_SSL_CACERT;
- case errSSLBadCert:
- failf(data, "SSL certificate problem: Couldn't understand the server "
- "certificate format");
- return CURLE_SSL_CONNECT_ERROR;
- /* These are all certificate problems with the client: */
- case errSecAuthFailed:
- failf(data, "SSL authentication failed");
- return CURLE_SSL_CONNECT_ERROR;
- case errSSLPeerHandshakeFail:
- failf(data, "SSL peer handshake failed, the server most likely "
- "requires a client certificate to connect");
- return CURLE_SSL_CONNECT_ERROR;
- case errSSLPeerUnknownCA:
- failf(data, "SSL server rejected the client certificate due to "
- "the certificate being signed by an unknown certificate "
- "authority");
- return CURLE_SSL_CONNECT_ERROR;
- /* This error is raised if the server's cert didn't match the server's
- host name: */
- case errSSLHostNameMismatch:
- failf(data, "SSL certificate peer verification failed, the "
- "certificate did not match \"%s\"\n", conn->host.dispname);
- return CURLE_PEER_FAILED_VERIFICATION;
- /* Generic handshake errors: */
- case errSSLConnectionRefused:
- failf(data, "Server dropped the connection during the SSL handshake");
- return CURLE_SSL_CONNECT_ERROR;
- case errSSLClosedAbort:
- failf(data, "Server aborted the SSL handshake");
- return CURLE_SSL_CONNECT_ERROR;
- case errSSLNegotiation:
- failf(data, "Could not negotiate an SSL cipher suite with the server");
- return CURLE_SSL_CONNECT_ERROR;
- /* Sometimes paramErr happens with buggy ciphers: */
- case paramErr: case errSSLInternal:
- failf(data, "Internal SSL engine error encountered during the "
- "SSL handshake");
- return CURLE_SSL_CONNECT_ERROR;
- case errSSLFatalAlert:
- failf(data, "Fatal SSL engine error encountered during the SSL "
- "handshake");
- return CURLE_SSL_CONNECT_ERROR;
- default:
- failf(data, "Unknown SSL protocol error in connection to %s:%d",
- conn->host.name, err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
- else {
- /* we have been connected fine, we're not waiting for anything else. */
- connssl->connecting_state = ssl_connect_3;
- /* Informational message */
- (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
- (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
- switch (protocol) {
- case kSSLProtocol2:
- infof(data, "SSL 2.0 connection using %s\n",
- SSLCipherNameForNumber(cipher));
- break;
- case kSSLProtocol3:
- infof(data, "SSL 3.0 connection using %s\n",
- SSLCipherNameForNumber(cipher));
- break;
- case kTLSProtocol1:
- infof(data, "TLS 1.0 connection using %s\n",
- TLSCipherNameForNumber(cipher));
- break;
- #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- case kTLSProtocol11:
- infof(data, "TLS 1.1 connection using %s\n",
- TLSCipherNameForNumber(cipher));
- break;
- case kTLSProtocol12:
- infof(data, "TLS 1.2 connection using %s\n",
- TLSCipherNameForNumber(cipher));
- break;
- #endif
- default:
- infof(data, "Unknown protocol connection\n");
- break;
- }
- return CURLE_OK;
- }
- }
- static CURLcode
- darwinssl_connect_step3(struct connectdata *conn,
- int sockindex)
- {
- struct SessionHandle *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- CFStringRef server_cert_summary;
- char server_cert_summary_c[128];
- CFArrayRef server_certs = NULL;
- SecCertificateRef server_cert;
- OSStatus err;
- CFIndex i, count;
- SecTrustRef trust = NULL;
- /* There is no step 3!
- * Well, okay, if verbose mode is on, let's print the details of the
- * server certificates. */
- #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
- #if CURL_BUILD_IOS
- #pragma unused(server_certs)
- err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
- /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
- a null trust, so be on guard for that: */
- if(err == noErr && trust) {
- count = SecTrustGetCertificateCount(trust);
- for(i = 0L ; i < count ; i++) {
- server_cert = SecTrustGetCertificateAtIndex(trust, i);
- server_cert_summary = CopyCertSubject(server_cert);
- memset(server_cert_summary_c, 0, 128);
- if(CFStringGetCString(server_cert_summary,
- server_cert_summary_c,
- 128,
- kCFStringEncodingUTF8)) {
- infof(data, "Server certificate: %s\n", server_cert_summary_c);
- }
- CFRelease(server_cert_summary);
- }
- CFRelease(trust);
- }
- #else
- /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion.
- The function SecTrustGetCertificateAtIndex() is officially present
- in Lion, but it is unfortunately also present in Snow Leopard as
- private API and doesn't work as expected. So we have to look for
- a different symbol to make sure this code is only executed under
- Lion or later. */
- if(SecTrustEvaluateAsync != NULL) {
- #pragma unused(server_certs)
- err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
- /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
- a null trust, so be on guard for that: */
- if(err == noErr && trust) {
- count = SecTrustGetCertificateCount(trust);
- for(i = 0L ; i < count ; i++) {
- server_cert = SecTrustGetCertificateAtIndex(trust, i);
- server_cert_summary = CopyCertSubject(server_cert);
- memset(server_cert_summary_c, 0, 128);
- if(CFStringGetCString(server_cert_summary,
- server_cert_summary_c,
- 128,
- kCFStringEncodingUTF8)) {
- infof(data, "Server certificate: %s\n", server_cert_summary_c);
- }
- CFRelease(server_cert_summary);
- }
- CFRelease(trust);
- }
- }
- else {
- #if CURL_SUPPORT_MAC_10_8
- err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
- /* Just in case SSLCopyPeerCertificates() returns null too... */
- if(err == noErr && server_certs) {
- count = CFArrayGetCount(server_certs);
- for(i = 0L ; i < count ; i++) {
- server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
- i);
- server_cert_summary = CopyCertSubject(server_cert);
- memset(server_cert_summary_c, 0, 128);
- if(CFStringGetCString(server_cert_summary,
- server_cert_summary_c,
- 128,
- kCFStringEncodingUTF8)) {
- infof(data, "Server certificate: %s\n", server_cert_summary_c);
- }
- CFRelease(server_cert_summary);
- }
- CFRelease(server_certs);
- }
- #endif /* CURL_SUPPORT_MAC_10_8 */
- }
- #endif /* CURL_BUILD_IOS */
- #else
- #pragma unused(trust)
- err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
- if(err == noErr) {
- count = CFArrayGetCount(server_certs);
- for(i = 0L ; i < count ; i++) {
- server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
- server_cert_summary = CopyCertSubject(server_cert);
- memset(server_cert_summary_c, 0, 128);
- if(CFStringGetCString(server_cert_summary,
- server_cert_summary_c,
- 128,
- kCFStringEncodingUTF8)) {
- infof(data, "Server certificate: %s\n", server_cert_summary_c);
- }
- CFRelease(server_cert_summary);
- }
- CFRelease(server_certs);
- }
- #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
- connssl->connecting_state = ssl_connect_done;
- return CURLE_OK;
- }
- static Curl_recv darwinssl_recv;
- static Curl_send darwinssl_send;
- static CURLcode
- darwinssl_connect_common(struct connectdata *conn,
- int sockindex,
- bool nonblocking,
- bool *done)
- {
- CURLcode retcode;
- struct SessionHandle *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- curl_socket_t sockfd = conn->sock[sockindex];
- long timeout_ms;
- int what;
- /* check if the connection has already been established */
- if(ssl_connection_complete == connssl->state) {
- *done = TRUE;
- return CURLE_OK;
- }
- if(ssl_connect_1==connssl->connecting_state) {
- /* Find out how much more time we're allowed */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
- if(timeout_ms < 0) {
- /* no need to continue if time already is up */
- failf(data, "SSL connection timeout");
- return CURLE_OPERATION_TIMEDOUT;
- }
- retcode = darwinssl_connect_step1(conn, sockindex);
- if(retcode)
- return retcode;
- }
- while(ssl_connect_2 == connssl->connecting_state ||
- ssl_connect_2_reading == connssl->connecting_state ||
- ssl_connect_2_writing == connssl->connecting_state) {
- /* check allowed time left */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
- if(timeout_ms < 0) {
- /* no need to continue if time already is up */
- failf(data, "SSL connection timeout");
- return CURLE_OPERATION_TIMEDOUT;
- }
- /* if ssl is expecting something, check if it's available. */
- if(connssl->connecting_state == ssl_connect_2_reading
- || connssl->connecting_state == ssl_connect_2_writing) {
- curl_socket_t writefd = ssl_connect_2_writing ==
- connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
- curl_socket_t readfd = ssl_connect_2_reading ==
- connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
- what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
- if(what < 0) {
- /* fatal error */
- failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
- return CURLE_SSL_CONNECT_ERROR;
- }
- else if(0 == what) {
- if(nonblocking) {
- *done = FALSE;
- return CURLE_OK;
- }
- else {
- /* timeout */
- failf(data, "SSL connection timeout");
- return CURLE_OPERATION_TIMEDOUT;
- }
- }
- /* socket is readable or writable */
- }
- /* Run transaction, and return to the caller if it failed or if this
- * connection is done nonblocking and this loop would execute again. This
- * permits the owner of a multi handle to abort a connection attempt
- * before step2 has completed while ensuring that a client using select()
- * or epoll() will always have a valid fdset to wait on.
- */
- retcode = darwinssl_connect_step2(conn, sockindex);
- if(retcode || (nonblocking &&
- (ssl_connect_2 == connssl->connecting_state ||
- ssl_connect_2_reading == connssl->connecting_state ||
- ssl_connect_2_writing == connssl->connecting_state)))
- return retcode;
- } /* repeat step2 until all transactions are done. */
- if(ssl_connect_3==connssl->connecting_state) {
- retcode = darwinssl_connect_step3(conn, sockindex);
- if(retcode)
- return retcode;
- }
- if(ssl_connect_done==connssl->connecting_state) {
- connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = darwinssl_recv;
- conn->send[sockindex] = darwinssl_send;
- *done = TRUE;
- }
- else
- *done = FALSE;
- /* Reset our connect state machine */
- connssl->connecting_state = ssl_connect_1;
- return CURLE_OK;
- }
- CURLcode
- Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
- {
- return darwinssl_connect_common(conn, sockindex, TRUE, done);
- }
- CURLcode
- Curl_darwinssl_connect(struct connectdata *conn,
- int sockindex)
- {
- CURLcode retcode;
- bool done = FALSE;
- retcode = darwinssl_connect_common(conn, sockindex, FALSE, &done);
- if(retcode)
- return retcode;
- DEBUGASSERT(done);
- return CURLE_OK;
- }
- void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
- {
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- if(connssl->ssl_ctx) {
- (void)SSLClose(connssl->ssl_ctx);
- #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- if(SSLCreateContext != NULL)
- CFRelease(connssl->ssl_ctx);
- #if CURL_SUPPORT_MAC_10_8
- else
- (void)SSLDisposeContext(connssl->ssl_ctx);
- #endif /* CURL_SUPPORT_MAC_10_8 */
- #else
- (void)SSLDisposeContext(connssl->ssl_ctx);
- #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- connssl->ssl_ctx = NULL;
- }
- connssl->ssl_sockfd = 0;
- }
- void Curl_darwinssl_close_all(struct SessionHandle *data)
- {
- /* SecureTransport doesn't separate sessions from contexts, so... */
- (void)data;
- }
- int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
- {
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct SessionHandle *data = conn->data;
- ssize_t nread;
- int what;
- int rc;
- char buf[120];
- if(!connssl->ssl_ctx)
- return 0;
- if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
- return 0;
- Curl_darwinssl_close(conn, sockindex);
- rc = 0;
- what = Curl_socket_ready(conn->sock[sockindex],
- CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
- for(;;) {
- if(what < 0) {
- /* anything that gets here is fatally bad */
- failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
- rc = -1;
- break;
- }
- if(!what) { /* timeout */
- failf(data, "SSL shutdown timeout");
- break;
- }
- /* Something to read, let's do it and hope that it is the close
- notify alert from the server. No way to SSL_Read now, so use read(). */
- nread = read(conn->sock[sockindex], buf, sizeof(buf));
- if(nread < 0) {
- failf(data, "read: %s", strerror(errno));
- rc = -1;
- }
- if(nread <= 0)
- break;
- what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
- }
- return rc;
- }
- void Curl_darwinssl_session_free(void *ptr)
- {
- /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
- cached session ID inside the Security framework. There is a private
- function that does this, but I don't want to have to explain to you why I
- got your application rejected from the App Store due to the use of a
- private API, so the best we can do is free up our own char array that we
- created way back in darwinssl_connect_step1... */
- Curl_safefree(ptr);
- }
- size_t Curl_darwinssl_version(char *buffer, size_t size)
- {
- return snprintf(buffer, size, "SecureTransport");
- }
- /*
- * This function uses SSLGetSessionState to determine connection status.
- *
- * Return codes:
- * 1 means the connection is still in place
- * 0 means the connection has been closed
- * -1 means the connection status is unknown
- */
- int Curl_darwinssl_check_cxn(struct connectdata *conn)
- {
- struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
- OSStatus err;
- SSLSessionState state;
- if(connssl->ssl_ctx) {
- err = SSLGetSessionState(connssl->ssl_ctx, &state);
- if(err == noErr)
- return state == kSSLConnected || state == kSSLHandshake;
- return -1;
- }
- return 0;
- }
- bool Curl_darwinssl_data_pending(const struct connectdata *conn,
- int connindex)
- {
- const struct ssl_connect_data *connssl = &conn->ssl[connindex];
- OSStatus err;
- size_t buffer;
- if(connssl->ssl_ctx) { /* SSL is in use */
- err = SSLGetBufferedReadSize(connssl->ssl_ctx, &buffer);
- if(err == noErr)
- return buffer > 0UL;
- return false;
- }
- else
- return false;
- }
- void Curl_darwinssl_random(struct SessionHandle *data,
- unsigned char *entropy,
- size_t length)
- {
- /* arc4random_buf() isn't available on cats older than Lion, so let's
- do this manually for the benefit of the older cats. */
- size_t i;
- u_int32_t random_number = 0;
- for(i = 0 ; i < length ; i++) {
- if(i % sizeof(u_int32_t) == 0)
- random_number = arc4random();
- entropy[i] = random_number & 0xFF;
- random_number >>= 8;
- }
- i = random_number = 0;
- (void)data;
- }
- void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
- {
- (void)md5len;
- (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
- }
- static ssize_t darwinssl_send(struct connectdata *conn,
- int sockindex,
- const void *mem,
- size_t len,
- CURLcode *curlcode)
- {
- /*struct SessionHandle *data = conn->data;*/
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- size_t processed = 0UL;
- OSStatus err;
- /* The SSLWrite() function works a little differently than expected. The
- fourth argument (processed) is currently documented in Apple's
- documentation as: "On return, the length, in bytes, of the data actually
- written."
- Now, one could interpret that as "written to the socket," but actually,
- it returns the amount of data that was written to a buffer internal to
- the SSLContextRef instead. So it's possible for SSLWrite() to return
- errSSLWouldBlock and a number of bytes "written" because those bytes were
- encrypted and written to a buffer, not to the socket.
- So if this happens, then we need to keep calling SSLWrite() over and
- over again with no new data until it quits returning errSSLWouldBlock. */
- /* Do we have buffered data to write from the last time we were called? */
- if(connssl->ssl_write_buffered_length) {
- /* Write the buffered data: */
- err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed);
- switch (err) {
- case noErr:
- /* processed is always going to be 0 because we didn't write to
- the buffer, so return how much was written to the socket */
- processed = connssl->ssl_write_buffered_length;
- connssl->ssl_write_buffered_length = 0UL;
- break;
- case errSSLWouldBlock: /* argh, try again */
- *curlcode = CURLE_AGAIN;
- return -1L;
- default:
- failf(conn->data, "SSLWrite() returned error %d", err);
- *curlcode = CURLE_SEND_ERROR;
- return -1L;
- }
- }
- else {
- /* We've got new data to write: */
- err = SSLWrite(connssl->ssl_ctx, mem, len, &processed);
- if(err != noErr) {
- switch (err) {
- case errSSLWouldBlock:
- /* Data was buffered but not sent, we have to tell the caller
- to try sending again, and remember how much was buffered */
- connssl->ssl_write_buffered_length = len;
- *curlcode = CURLE_AGAIN;
- return -1L;
- default:
- failf(conn->data, "SSLWrite() returned error %d", err);
- *curlcode = CURLE_SEND_ERROR;
- return -1L;
- }
- }
- }
- return (ssize_t)processed;
- }
- static ssize_t darwinssl_recv(struct connectdata *conn,
- int num,
- char *buf,
- size_t buffersize,
- CURLcode *curlcode)
- {
- /*struct SessionHandle *data = conn->data;*/
- struct ssl_connect_data *connssl = &conn->ssl[num];
- size_t processed = 0UL;
- OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed);
- if(err != noErr) {
- switch (err) {
- case errSSLWouldBlock: /* return how much we read (if anything) */
- if(processed)
- return (ssize_t)processed;
- *curlcode = CURLE_AGAIN;
- return -1L;
- break;
- /* errSSLClosedGraceful - server gracefully shut down the SSL session
- errSSLClosedNoNotify - server hung up on us instead of sending a
- closure alert notice, read() is returning 0
- Either way, inform the caller that the server disconnected. */
- case errSSLClosedGraceful:
- case errSSLClosedNoNotify:
- *curlcode = CURLE_OK;
- return -1L;
- break;
- default:
- failf(conn->data, "SSLRead() return error %d", err);
- *curlcode = CURLE_RECV_ERROR;
- return -1L;
- break;
- }
- }
- return (ssize_t)processed;
- }
- #endif /* USE_DARWINSSL */
|