12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326 |
- /***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2020, 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 https://curl.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 macOS 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 Curl_easy definition */
- #include "curl_base64.h"
- #include "strtok.h"
- #include "multiif.h"
- #ifdef USE_SECTRANSP
- #ifdef __clang__
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wtautological-pointer-compare"
- #endif /* __clang__ */
- #include <limits.h>
- #include <Security/Security.h>
- /* For some reason, when building for iOS, the omnibus header above does
- * not include SecureTransport.h as of iOS SDK 5.1. */
- #include <Security/SecureTransport.h>
- #include <CoreFoundation/CoreFoundation.h>
- #include <CommonCrypto/CommonDigest.h>
- /* The Security framework has changed greatly between iOS and different macOS
- 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.
- In general, you want to build this using the most recent OS SDK, since some
- features require curl to be built against the latest SDK. TLS 1.1 and 1.2
- support, for instance, require the macOS 10.8 SDK or later. TLS 1.3
- requires the macOS 10.13 or iOS 11 SDK or later. */
- #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
- #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
- #error "The Secure Transport 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_IOS_9 0
- #define CURL_BUILD_IOS_11 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
- #define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
- #define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
- /* 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 using the compiler command line option
- "-mmacosx-version-min.") */
- #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_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000
- #define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
- #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_BUILD_MAC_10_9 0
- #define CURL_BUILD_MAC_10_11 0
- #define CURL_BUILD_MAC_10_13 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
- #define CURL_SUPPORT_MAC_10_9 0
- #else
- #error "The Secure Transport back-end requires iOS or macOS."
- #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 "sectransp.h"
- #include "curl_printf.h"
- #include "strdup.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
- struct ssl_backend_data {
- SSLContextRef ssl_ctx;
- curl_socket_t ssl_sockfd;
- bool ssl_direction; /* true if writing, false if reading */
- size_t ssl_write_buffered_length;
- };
- /* pinned public key support tests */
- /* version 1 supports macOS 10.12+ and iOS 10+ */
- #if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
- (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
- #define SECTRANSP_PINNEDPUBKEY_V1 1
- #endif
- /* version 2 supports MacOSX 10.7+ */
- #if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
- #define SECTRANSP_PINNEDPUBKEY_V2 1
- #endif
- #if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2)
- /* this backend supports CURLOPT_PINNEDPUBLICKEY */
- #define SECTRANSP_PINNEDPUBKEY 1
- #endif /* SECTRANSP_PINNEDPUBKEY */
- #ifdef SECTRANSP_PINNEDPUBKEY
- /* both new and old APIs return rsa keys missing the spki header (not DER) */
- static const unsigned char rsa4096SpkiHeader[] = {
- 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
- 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
- 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00};
- static const unsigned char rsa2048SpkiHeader[] = {
- 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
- 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
- 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00};
- #ifdef SECTRANSP_PINNEDPUBKEY_V1
- /* the *new* version doesn't return DER encoded ecdsa certs like the old... */
- static const unsigned char ecDsaSecp256r1SpkiHeader[] = {
- 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
- 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
- 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
- 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
- 0x42, 0x00};
- static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
- 0x30, 0x76, 0x30, 0x10, 0x06, 0x07,
- 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
- 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04,
- 0x00, 0x22, 0x03, 0x62, 0x00};
- #endif /* SECTRANSP_PINNEDPUBKEY_V1 */
- #endif /* SECTRANSP_PINNEDPUBKEY */
- /* 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;
- struct ssl_backend_data *backend = connssl->backend;
- int sock = backend->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;
- backend->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;
- struct ssl_backend_data *backend = connssl->backend;
- int sock = backend->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;
- backend->ssl_direction = true;
- }
- else {
- ortn = ioErr;
- }
- }
- else {
- ortn = noErr;
- }
- *dataLength = bytesSent;
- return ortn;
- }
- #ifndef CURL_DISABLE_VERBOSE_STRINGS
- 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 */
- #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
- /* New ChaCha20+Poly1305 cipher-suites used by TLS 1.3: */
- case TLS_AES_128_GCM_SHA256:
- return "TLS_AES_128_GCM_SHA256";
- break;
- case TLS_AES_256_GCM_SHA384:
- return "TLS_AES_256_GCM_SHA384";
- break;
- case TLS_CHACHA20_POLY1305_SHA256:
- return "TLS_CHACHA20_POLY1305_SHA256";
- break;
- case TLS_AES_128_CCM_SHA256:
- return "TLS_AES_128_CCM_SHA256";
- break;
- case TLS_AES_128_CCM_8_SHA256:
- return "TLS_AES_128_CCM_8_SHA256";
- break;
- case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
- return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
- break;
- case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
- return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256";
- break;
- #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
- }
- return "TLS_NULL_WITH_NULL_NULL";
- }
- #endif /* !CURL_DISABLE_VERBOSE_STRINGS */
- #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;
- char *tok_buf;
- /* 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_r(os_version, ".", &tok_buf);
- os_version_minor = strtok_r(NULL, ".", &tok_buf);
- *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 getsubject(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;
- }
- static CURLcode CopyCertSubject(struct Curl_easy *data,
- SecCertificateRef cert, char **certp)
- {
- CFStringRef c = getsubject(cert);
- CURLcode result = CURLE_OK;
- const char *direct;
- char *cbuf = NULL;
- *certp = NULL;
- if(!c) {
- failf(data, "SSL: invalid CA certificate subject");
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- /* If the subject is already available as UTF-8 encoded (ie 'direct') then
- use that, else convert it. */
- direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8);
- if(direct) {
- *certp = strdup(direct);
- if(!*certp) {
- failf(data, "SSL: out of memory");
- result = CURLE_OUT_OF_MEMORY;
- }
- }
- else {
- size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
- cbuf = calloc(cbuf_size, 1);
- if(cbuf) {
- if(!CFStringGetCString(c, cbuf, cbuf_size,
- kCFStringEncodingUTF8)) {
- failf(data, "SSL: invalid CA certificate subject");
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
- else
- /* pass back the buffer */
- *certp = cbuf;
- }
- else {
- failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size);
- result = CURLE_OUT_OF_MEMORY;
- }
- }
- if(result)
- free(cbuf);
- CFRelease(c);
- return result;
- }
- #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
- CFArrayRef keys_list;
- CFIndex keys_list_count;
- CFIndex i;
- CFStringRef common_name;
- /* 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[5];
- CFTypeRef values[5];
- 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] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the
- * label matching below worked correctly */
- keys[2] = kSecMatchLimit;
- /* identity searches need a SecPolicyRef in order to work */
- values[3] = SecPolicyCreateSSL(false, NULL);
- keys[3] = kSecMatchPolicy;
- /* match the name of the certificate (doesn't work in macOS 10.12.1) */
- values[4] = label_cf;
- keys[4] = kSecAttrLabel;
- query_dict = CFDictionaryCreate(NULL, (const void **)keys,
- (const void **)values, 5L,
- &kCFCopyStringDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFRelease(values[3]);
- /* Do we have a match? */
- status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list);
- /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity,
- * we need to find the correct identity ourselves */
- if(status == noErr) {
- keys_list_count = CFArrayGetCount(keys_list);
- *out_cert_and_key = NULL;
- status = 1;
- for(i = 0; i<keys_list_count; i++) {
- OSStatus err = noErr;
- SecCertificateRef cert = NULL;
- SecIdentityRef identity =
- (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
- err = SecIdentityCopyCertificate(identity, &cert);
- if(err == noErr) {
- #if CURL_BUILD_IOS
- common_name = SecCertificateCopySubjectSummary(cert);
- #elif CURL_BUILD_MAC_10_7
- SecCertificateCopyCommonName(cert, &common_name);
- #endif
- if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
- CFRelease(cert);
- CFRelease(common_name);
- CFRetain(identity);
- *out_cert_and_key = identity;
- status = noErr;
- break;
- }
- CFRelease(common_name);
- }
- CFRelease(cert);
- }
- }
- if(keys_list)
- CFRelease(keys_list);
- CFRelease(query_dict);
- CFRelease(label_cf);
- }
- 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_6 */
- }
- #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 struct curl_blob *blob,
- const char *cPassword,
- SecIdentityRef *out_cert_and_key)
- {
- OSStatus status = errSecItemNotFound;
- CFURLRef pkcs_url = NULL;
- 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
- bool resource_imported;
- if(blob) {
- pkcs_data = CFDataCreate(kCFAllocatorDefault,
- (const unsigned char *)blob->data, blob->len);
- status = (pkcs_data != NULL) ? errSecSuccess : errSecAllocate;
- resource_imported = (pkcs_data != NULL);
- }
- else {
- pkcs_url =
- CFURLCreateFromFileSystemRepresentation(NULL,
- (const UInt8 *)cPath,
- strlen(cPath), false);
- resource_imported =
- CFURLCreateDataAndPropertiesFromResource(NULL,
- pkcs_url, &pkcs_data,
- NULL, NULL, &status);
- }
- if(resource_imported) {
- CFArrayRef items = NULL;
- /* On iOS SecPKCS12Import will never add the client certificate to the
- * Keychain.
- *
- * It gives us back a SecIdentityRef that we can use directly. */
- #if CURL_BUILD_IOS
- const void *cKeys[] = {kSecImportExportPassphrase};
- const void *cValues[] = {password};
- CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
- password ? 1L : 0L, NULL, NULL);
- if(options != NULL) {
- status = SecPKCS12Import(pkcs_data, options, &items);
- CFRelease(options);
- }
- /* On macOS SecPKCS12Import will always add the client certificate to
- * the Keychain.
- *
- * As this doesn't match iOS, and apps may not want to see their client
- * certificate saved in the user's keychain, we use SecItemImport
- * with a NULL keychain to avoid importing it.
- *
- * This returns a SecCertificateRef from which we can construct a
- * SecIdentityRef.
- */
- #elif CURL_BUILD_MAC_10_7
- SecItemImportExportKeyParameters keyParams;
- SecExternalFormat inputFormat = kSecFormatPKCS12;
- SecExternalItemType inputType = kSecItemTypeCertificate;
- memset(&keyParams, 0x00, sizeof(keyParams));
- keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
- keyParams.passphrase = password;
- status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType,
- 0, &keyParams, NULL, &items);
- #endif
- /* Extract the SecIdentityRef */
- if(status == errSecSuccess && items && CFArrayGetCount(items)) {
- CFIndex i, count;
- count = CFArrayGetCount(items);
- for(i = 0; i < count; i++) {
- CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i);
- CFTypeID itemID = CFGetTypeID(item);
- if(itemID == CFDictionaryGetTypeID()) {
- CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue(
- (CFDictionaryRef) item,
- kSecImportItemIdentity);
- CFRetain(identity);
- *out_cert_and_key = (SecIdentityRef) identity;
- break;
- }
- #if CURL_BUILD_MAC_10_7
- else if(itemID == SecCertificateGetTypeID()) {
- status = SecIdentityCreateWithCertificate(NULL,
- (SecCertificateRef) item,
- out_cert_and_key);
- break;
- }
- #endif
- }
- }
- if(items)
- CFRelease(items);
- CFRelease(pkcs_data);
- }
- #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
- if(password)
- CFRelease(password);
- if(pkcs_url)
- 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;
- }
- #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver,
- long ssl_version)
- {
- switch(ssl_version) {
- case CURL_SSLVERSION_TLSv1_0:
- *darwinver = kTLSProtocol1;
- return CURLE_OK;
- case CURL_SSLVERSION_TLSv1_1:
- *darwinver = kTLSProtocol11;
- return CURLE_OK;
- case CURL_SSLVERSION_TLSv1_2:
- *darwinver = kTLSProtocol12;
- return CURLE_OK;
- case CURL_SSLVERSION_TLSv1_3:
- /* TLS 1.3 support first appeared in iOS 11 and macOS 10.13 */
- #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
- if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
- *darwinver = kTLSProtocol13;
- return CURLE_OK;
- }
- #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
- HAVE_BUILTIN_AVAILABLE == 1 */
- break;
- }
- return CURLE_SSL_CONNECT_ERROR;
- }
- #endif
- static CURLcode
- set_ssl_version_min_max(struct connectdata *conn, int sockindex)
- {
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- long ssl_version = SSL_CONN_CONFIG(version);
- long ssl_version_max = SSL_CONN_CONFIG(version_max);
- long max_supported_version_by_os;
- /* macOS 10.5-10.7 supported TLS 1.0 only.
- macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2.
- macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */
- #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
- if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
- max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3;
- }
- else {
- max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
- }
- #else
- max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
- #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
- HAVE_BUILTIN_AVAILABLE == 1 */
- switch(ssl_version) {
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- ssl_version = CURL_SSLVERSION_TLSv1_0;
- break;
- }
- switch(ssl_version_max) {
- case CURL_SSLVERSION_MAX_NONE:
- case CURL_SSLVERSION_MAX_DEFAULT:
- ssl_version_max = max_supported_version_by_os;
- break;
- }
- #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- if(SSLSetProtocolVersionMax != NULL) {
- SSLProtocol darwin_ver_min = kTLSProtocol1;
- SSLProtocol darwin_ver_max = kTLSProtocol1;
- CURLcode result = sectransp_version_from_curl(&darwin_ver_min,
- ssl_version);
- if(result) {
- failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
- return result;
- }
- result = sectransp_version_from_curl(&darwin_ver_max,
- ssl_version_max >> 16);
- if(result) {
- failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
- return result;
- }
- (void)SSLSetProtocolVersionMin(backend->ssl_ctx, darwin_ver_min);
- (void)SSLSetProtocolVersionMax(backend->ssl_ctx, darwin_ver_max);
- return result;
- }
- else {
- #if CURL_SUPPORT_MAC_10_8
- long i = ssl_version;
- (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kSSLProtocolAll,
- false);
- for(; i <= (ssl_version_max >> 16); i++) {
- switch(i) {
- case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kTLSProtocol1,
- true);
- break;
- case CURL_SSLVERSION_TLSv1_1:
- (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kTLSProtocol11,
- true);
- break;
- case CURL_SSLVERSION_TLSv1_2:
- (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kTLSProtocol12,
- true);
- break;
- case CURL_SSLVERSION_TLSv1_3:
- failf(data, "Your version of the OS does not support TLSv1.3");
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
- return CURLE_OK;
- #endif /* CURL_SUPPORT_MAC_10_8 */
- }
- #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- failf(data, "Secure Transport: cannot set SSL protocol");
- return CURLE_SSL_CONNECT_ERROR;
- }
- static CURLcode sectransp_connect_step1(struct connectdata *conn,
- int sockindex)
- {
- struct Curl_easy *data = conn->data;
- curl_socket_t sockfd = conn->sock[sockindex];
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
- const struct curl_blob *ssl_cablob = NULL;
- const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
- const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
- #ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
- #else
- const char * const hostname = conn->host.name;
- const long int port = conn->remote_port;
- #endif
- #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;
- 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 available */
- if(backend->ssl_ctx)
- CFRelease(backend->ssl_ctx);
- backend->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
- if(!backend->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(backend->ssl_ctx)
- (void)SSLDisposeContext(backend->ssl_ctx);
- err = SSLNewContext(false, &(backend->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(backend->ssl_ctx)
- (void)SSLDisposeContext(backend->ssl_ctx);
- err = SSLNewContext(false, &(backend->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 */
- backend->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(conn->ssl_config.version) {
- case CURL_SSLVERSION_TLSv1:
- (void)SSLSetProtocolVersionMin(backend->ssl_ctx, kTLSProtocol1);
- #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
- if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
- (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol13);
- }
- else {
- (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
- }
- #else
- (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
- #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
- HAVE_BUILTIN_AVAILABLE == 1 */
- break;
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1_0:
- case CURL_SSLVERSION_TLSv1_1:
- case CURL_SSLVERSION_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_3:
- {
- CURLcode result = set_ssl_version_min_max(conn, sockindex);
- if(result != CURLE_OK)
- return result;
- break;
- }
- case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol3);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv3");
- return CURLE_SSL_CONNECT_ERROR;
- }
- (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol3);
- break;
- case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol2);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
- }
- (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol2);
- break;
- default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
- else {
- #if CURL_SUPPORT_MAC_10_8
- (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kSSLProtocolAll,
- false);
- switch(conn->ssl_config.version) {
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kTLSProtocol1,
- true);
- (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kTLSProtocol11,
- true);
- (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kTLSProtocol12,
- true);
- break;
- case CURL_SSLVERSION_TLSv1_0:
- case CURL_SSLVERSION_TLSv1_1:
- case CURL_SSLVERSION_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_3:
- {
- CURLcode result = set_ssl_version_min_max(conn, sockindex);
- if(result != CURLE_OK)
- return result;
- break;
- }
- case CURL_SSLVERSION_SSLv3:
- err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kSSLProtocol3,
- true);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv3");
- return CURLE_SSL_CONNECT_ERROR;
- }
- break;
- case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kSSLProtocol2,
- true);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
- }
- break;
- default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
- return CURLE_SSL_CONNECT_ERROR;
- }
- #endif /* CURL_SUPPORT_MAC_10_8 */
- }
- #else
- if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) {
- failf(data, "Your version of the OS does not support to set maximum"
- " SSL/TLS version");
- return CURLE_SSL_CONNECT_ERROR;
- }
- (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, false);
- switch(conn->ssl_config.version) {
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionEnabled(backend->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_TLSv1_3:
- failf(data, "Your version of the OS does not support TLSv1.3");
- return CURLE_SSL_CONNECT_ERROR;
- case CURL_SSLVERSION_SSLv2:
- err = SSLSetProtocolVersionEnabled(backend->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:
- err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
- kSSLProtocol3,
- true);
- if(err != noErr) {
- failf(data, "Your version of the OS does not support SSLv3");
- return CURLE_SSL_CONNECT_ERROR;
- }
- break;
- default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
- return CURLE_SSL_CONNECT_ERROR;
- }
- #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
- if(conn->bits.tls_enable_alpn) {
- if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
- CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
- &kCFTypeArrayCallBacks);
- #ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2
- #ifndef CURL_DISABLE_PROXY
- && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
- #endif
- ) {
- CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID));
- infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
- }
- #endif
- CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
- infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
- /* expects length prefixed preference ordered list of protocols in wire
- * format
- */
- err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr);
- if(err != noErr)
- infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n",
- err);
- CFRelease(alpnArr);
- }
- }
- #endif
- if(SSL_SET_OPTION(key)) {
- infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
- "Transport. The private key must be in the Keychain.\n");
- }
- if(ssl_cert || ssl_cert_blob) {
- bool is_cert_data = ssl_cert_blob != NULL;
- bool is_cert_file = (!is_cert_data) && is_file(ssl_cert);
- SecIdentityRef cert_and_key = NULL;
- /* 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 || is_cert_data) {
- if(!SSL_SET_OPTION(cert_type))
- infof(data, "WARNING: SSL: Certificate type not set, assuming "
- "PKCS#12 format.\n");
- else if(strncmp(SSL_SET_OPTION(cert_type), "P12",
- strlen(SSL_SET_OPTION(cert_type))) != 0)
- infof(data, "WARNING: SSL: The Security framework only supports "
- "loading identities that are in PKCS#12 format.\n");
- err = CopyIdentityFromPKCS12File(ssl_cert, ssl_cert_blob,
- SSL_SET_OPTION(key_passwd), &cert_and_key);
- }
- else
- err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
- if(err == noErr && cert_and_key) {
- 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) {
- char *certp;
- CURLcode result = CopyCertSubject(data, cert, &certp);
- if(!result) {
- infof(data, "Client certificate: %s\n", certp);
- free(certp);
- }
- CFRelease(cert);
- if(result == CURLE_PEER_FAILED_VERIFICATION)
- return CURLE_SSL_CERTPROBLEM;
- if(result)
- return result;
- }
- certs_c[0] = cert_and_key;
- certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
- &kCFTypeArrayCallBacks);
- err = SSLSetCertificate(backend->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 {
- const char *cert_showfilename_error =
- is_cert_data ? "(memory blob)" : ssl_cert;
- switch(err) {
- case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
- failf(data, "SSL: Incorrect password for the certificate \"%s\" "
- "and its private key.", cert_showfilename_error);
- 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.",
- cert_showfilename_error);
- break;
- case -25260: /* errSecPassphraseRequired */
- failf(data, "SSL The certificate \"%s\" requires a password.",
- cert_showfilename_error);
- break;
- case errSecItemNotFound:
- failf(data, "SSL: Can't find the certificate \"%s\" and its private "
- "key in the Keychain.", cert_showfilename_error);
- break;
- default:
- failf(data, "SSL: Can't load the certificate \"%s\" and its private "
- "key: OSStatus %d", cert_showfilename_error, 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, Lion or
- Mountain 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 11.x.x is Lion (10.7)
- Darwin 12.x.x is Mountain Lion (10.8)
- Darwin 13.x.x is Mavericks (10.9)
- Darwin 14.x.x is Yosemite (10.10)
- Darwin 15.x.x is El Capitan (10.11)
- */
- #if CURL_BUILD_MAC
- if(SSLSetSessionOption != NULL && darwinver_maj >= 13) {
- #else
- if(SSLSetSessionOption != NULL) {
- #endif /* CURL_BUILD_MAC */
- bool break_on_auth = !conn->ssl_config.verifypeer ||
- ssl_cafile || ssl_cablob;
- err = SSLSetSessionOption(backend->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(backend->ssl_ctx,
- conn->ssl_config.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(backend->ssl_ctx,
- conn->ssl_config.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((ssl_cafile || ssl_cablob) && verifypeer) {
- bool is_cert_data = ssl_cablob != NULL;
- bool is_cert_file = (!is_cert_data) && is_file(ssl_cafile);
- if(!(is_cert_file || is_cert_data)) {
- failf(data, "SSL: can't load CA certificate file %s", ssl_cafile);
- return CURLE_SSL_CACERT_BADFILE;
- }
- }
- /* Configure hostname check. SNI is used if available.
- * Both hostname check and SNI require SSLSetPeerDomainName().
- * Also: the verifyhost setting influences SNI usage */
- if(conn->ssl_config.verifyhost) {
- err = SSLSetPeerDomainName(backend->ssl_ctx, hostname,
- strlen(hostname));
- if(err != noErr) {
- infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
- err);
- }
- if((Curl_inet_pton(AF_INET, hostname, &addr))
- #ifdef ENABLE_IPV6
- || (Curl_inet_pton(AF_INET6, hostname, &addr))
- #endif
- ) {
- infof(data, "WARNING: using IP address, SNI is being disabled by "
- "the OS.\n");
- }
- }
- else {
- infof(data, "WARNING: disabling hostname validation also disables SNI.\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.) */
- err = SSLGetNumberSupportedCiphers(backend->ssl_ctx, &all_ciphers_count);
- if(err != noErr) {
- failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d",
- err);
- return CURLE_SSL_CIPHER;
- }
- all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
- if(!all_ciphers) {
- failf(data, "SSL: Failed to allocate memory for all ciphers");
- return CURLE_OUT_OF_MEMORY;
- }
- allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
- if(!allowed_ciphers) {
- Curl_safefree(all_ciphers);
- failf(data, "SSL: Failed to allocate memory for allowed ciphers");
- return CURLE_OUT_OF_MEMORY;
- }
- err = SSLGetSupportedCiphers(backend->ssl_ctx, all_ciphers,
- &all_ciphers_count);
- if(err != noErr) {
- Curl_safefree(all_ciphers);
- Curl_safefree(allowed_ciphers);
- return CURLE_SSL_CIPHER;
- }
- 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:
- /* Disable RC4: */
- case SSL_RSA_WITH_RC4_128_MD5:
- case SSL_RSA_WITH_RC4_128_SHA:
- case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
- case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/
- case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */
- case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
- case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */
- case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */
- case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */
- break;
- default: /* enable everything else */
- allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
- break;
- }
- }
- err = SSLSetEnabledCiphers(backend->ssl_ctx, allowed_ciphers,
- allowed_ciphers_count);
- Curl_safefree(all_ciphers);
- Curl_safefree(allowed_ciphers);
- if(err != noErr) {
- failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
- return CURLE_SSL_CIPHER;
- }
- #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(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
- !data->set.ssl.enable_beast);
- SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart,
- data->set.ssl.falsestart); /* false start support */
- }
- #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
- /* Check if there's a cached ID we can/should use here! */
- if(SSL_SET_OPTION(primary.sessionid)) {
- char *ssl_sessionid;
- size_t ssl_sessionid_len;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
- &ssl_sessionid_len, sockindex)) {
- /* we got a session id, use it! */
- err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
- Curl_ssl_sessionid_unlock(conn);
- 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 result;
- ssl_sessionid =
- aprintf("%s:%d:%d:%s:%ld", ssl_cafile,
- verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
- ssl_sessionid_len = strlen(ssl_sessionid);
- err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
- if(err != noErr) {
- Curl_ssl_sessionid_unlock(conn);
- failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
- result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len,
- sockindex);
- Curl_ssl_sessionid_unlock(conn);
- if(result) {
- failf(data, "failed to store ssl session");
- return result;
- }
- }
- }
- err = SSLSetIOFuncs(backend->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. */
- backend->ssl_sockfd = sockfd;
- err = SSLSetConnection(backend->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 long pem_to_der(const char *in, unsigned char **out, size_t *outlen)
- {
- char *sep_start, *sep_end, *cert_start, *cert_end;
- size_t i, j, err;
- size_t len;
- unsigned char *b64;
- /* Jump through the separators at the beginning of the certificate. */
- sep_start = strstr(in, "-----");
- if(sep_start == NULL)
- return 0;
- cert_start = strstr(sep_start + 1, "-----");
- if(cert_start == NULL)
- return -1;
- cert_start += 5;
- /* Find separator after the end of the certificate. */
- cert_end = strstr(cert_start, "-----");
- if(cert_end == NULL)
- return -1;
- sep_end = strstr(cert_end + 1, "-----");
- if(sep_end == NULL)
- return -1;
- sep_end += 5;
- len = cert_end - cert_start;
- b64 = malloc(len + 1);
- if(!b64)
- return -1;
- /* Create base64 string without linefeeds. */
- for(i = 0, j = 0; i < len; i++) {
- if(cert_start[i] != '\r' && cert_start[i] != '\n')
- b64[j++] = cert_start[i];
- }
- b64[j] = '\0';
- err = Curl_base64_decode((const char *)b64, out, outlen);
- free(b64);
- if(err) {
- free(*out);
- return -1;
- }
- return sep_end - in;
- }
- static int read_cert(const char *file, unsigned char **out, size_t *outlen)
- {
- int fd;
- ssize_t n, len = 0, cap = 512;
- unsigned char buf[512], *data;
- 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 = Curl_saferealloc(data, cap);
- if(!data) {
- close(fd);
- return -1;
- }
- }
- memcpy(data + len, buf, n);
- len += n;
- }
- data[len] = '\0';
- *out = data;
- *outlen = len;
- return 0;
- }
- static int append_cert_to_array(struct Curl_easy *data,
- unsigned char *buf, size_t buflen,
- CFMutableArrayRef array)
- {
- CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
- char *certp;
- CURLcode result;
- 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_BADFILE;
- }
- /* Check if cacert is valid. */
- result = CopyCertSubject(data, cacert, &certp);
- switch(result) {
- case CURLE_OK:
- break;
- case CURLE_PEER_FAILED_VERIFICATION:
- return CURLE_SSL_CACERT_BADFILE;
- case CURLE_OUT_OF_MEMORY:
- default:
- return result;
- }
- free(certp);
- CFArrayAppendValue(array, cacert);
- CFRelease(cacert);
- return CURLE_OK;
- }
- static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
- SSLContextRef ctx)
- {
- int n = 0, rc;
- long res;
- unsigned char *certbuf, *der;
- size_t buflen, derlen, offset = 0;
- if(read_cert(cafile, &certbuf, &buflen) < 0) {
- failf(data, "SSL: failed to read or invalid CA certificate");
- return CURLE_SSL_CACERT_BADFILE;
- }
- /*
- * Certbuf now contains the contents of the certificate file, which can be
- * - a single DER certificate,
- * - a single PEM certificate or
- * - a bunch of PEM certificates (certificate bundle).
- *
- * Go through certbuf, and convert any PEM certificate in it into DER
- * format.
- */
- CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks);
- if(array == NULL) {
- free(certbuf);
- failf(data, "SSL: out of memory creating CA certificate array");
- return CURLE_OUT_OF_MEMORY;
- }
- while(offset < buflen) {
- n++;
- /*
- * Check if the certificate is in PEM format, and convert it to DER. If
- * this fails, we assume the certificate is in DER format.
- */
- res = pem_to_der((const char *)certbuf + offset, &der, &derlen);
- if(res < 0) {
- free(certbuf);
- CFRelease(array);
- failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle",
- n, offset);
- return CURLE_SSL_CACERT_BADFILE;
- }
- offset += res;
- if(res == 0 && offset == 0) {
- /* This is not a PEM file, probably a certificate in DER format. */
- rc = append_cert_to_array(data, certbuf, buflen, array);
- free(certbuf);
- if(rc != CURLE_OK) {
- CFRelease(array);
- return rc;
- }
- break;
- }
- else if(res == 0) {
- /* No more certificates in the bundle. */
- free(certbuf);
- break;
- }
- rc = append_cert_to_array(data, der, derlen, array);
- free(der);
- if(rc != CURLE_OK) {
- free(certbuf);
- CFRelease(array);
- return rc;
- }
- }
- SecTrustRef trust;
- OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
- if(trust == NULL) {
- failf(data, "SSL: error getting certificate chain");
- CFRelease(array);
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- else if(ret != noErr) {
- CFRelease(array);
- failf(data, "SSLCopyPeerTrust() returned error %d", ret);
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- ret = SecTrustSetAnchorCertificates(trust, array);
- if(ret != noErr) {
- CFRelease(array);
- CFRelease(trust);
- failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- ret = SecTrustSetAnchorCertificatesOnly(trust, true);
- if(ret != noErr) {
- CFRelease(array);
- CFRelease(trust);
- failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret);
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- SecTrustResultType trust_eval = 0;
- ret = SecTrustEvaluate(trust, &trust_eval);
- CFRelease(array);
- CFRelease(trust);
- if(ret != noErr) {
- failf(data, "SecTrustEvaluate() returned error %d", ret);
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- switch(trust_eval) {
- case kSecTrustResultUnspecified:
- case kSecTrustResultProceed:
- return CURLE_OK;
- case kSecTrustResultRecoverableTrustFailure:
- case kSecTrustResultDeny:
- default:
- failf(data, "SSL: certificate verification failed (result: %d)",
- trust_eval);
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- }
- #ifdef SECTRANSP_PINNEDPUBKEY
- static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
- SSLContextRef ctx,
- const char *pinnedpubkey)
- { /* Scratch */
- size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24;
- unsigned char *pubkey = NULL, *realpubkey = NULL;
- const unsigned char *spkiHeader = NULL;
- CFDataRef publicKeyBits = NULL;
- /* Result is returned to caller */
- CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- /* if a path wasn't specified, don't pin */
- if(!pinnedpubkey)
- return CURLE_OK;
- if(!ctx)
- return result;
- do {
- SecTrustRef trust;
- OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
- if(ret != noErr || trust == NULL)
- break;
- SecKeyRef keyRef = SecTrustCopyPublicKey(trust);
- CFRelease(trust);
- if(keyRef == NULL)
- break;
- #ifdef SECTRANSP_PINNEDPUBKEY_V1
- publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
- CFRelease(keyRef);
- if(publicKeyBits == NULL)
- break;
- #elif SECTRANSP_PINNEDPUBKEY_V2
- OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
- &publicKeyBits);
- CFRelease(keyRef);
- if(success != errSecSuccess || publicKeyBits == NULL)
- break;
- #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
- pubkeylen = CFDataGetLength(publicKeyBits);
- pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits);
- switch(pubkeylen) {
- case 526:
- /* 4096 bit RSA pubkeylen == 526 */
- spkiHeader = rsa4096SpkiHeader;
- break;
- case 270:
- /* 2048 bit RSA pubkeylen == 270 */
- spkiHeader = rsa2048SpkiHeader;
- break;
- #ifdef SECTRANSP_PINNEDPUBKEY_V1
- case 65:
- /* ecDSA secp256r1 pubkeylen == 65 */
- spkiHeader = ecDsaSecp256r1SpkiHeader;
- spkiHeaderLength = 26;
- break;
- case 97:
- /* ecDSA secp384r1 pubkeylen == 97 */
- spkiHeader = ecDsaSecp384r1SpkiHeader;
- spkiHeaderLength = 23;
- break;
- default:
- infof(data, "SSL: unhandled public key length: %d\n", pubkeylen);
- #elif SECTRANSP_PINNEDPUBKEY_V2
- default:
- /* ecDSA secp256r1 pubkeylen == 91 header already included?
- * ecDSA secp384r1 header already included too
- * we assume rest of algorithms do same, so do nothing
- */
- result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey,
- pubkeylen);
- #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
- continue; /* break from loop */
- }
- realpubkeylen = pubkeylen + spkiHeaderLength;
- realpubkey = malloc(realpubkeylen);
- if(!realpubkey)
- break;
- memcpy(realpubkey, spkiHeader, spkiHeaderLength);
- memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen);
- result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey,
- realpubkeylen);
- } while(0);
- Curl_safefree(realpubkey);
- if(publicKeyBits != NULL)
- CFRelease(publicKeyBits);
- return result;
- }
- #endif /* SECTRANSP_PINNEDPUBKEY */
- static CURLcode
- sectransp_connect_step2(struct connectdata *conn, int sockindex)
- {
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- OSStatus err;
- SSLCipherSuite cipher;
- SSLProtocol protocol = 0;
- #ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- #else
- const char * const hostname = conn->host.name;
- #endif
- 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(backend->ssl_ctx);
- if(err != noErr) {
- switch(err) {
- case errSSLWouldBlock: /* they're not done with us yet */
- connssl->connecting_state = backend->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(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
- CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data,
- backend->ssl_ctx);
- if(result)
- return result;
- }
- /* the documentation says we need to call SSLHandshake() again */
- return sectransp_connect_step2(conn, sockindex);
- /* Problem with encrypt / decrypt */
- case errSSLPeerDecodeError:
- failf(data, "Decode failed");
- break;
- case errSSLDecryptionFail:
- case errSSLPeerDecryptionFail:
- failf(data, "Decryption failed");
- break;
- case errSSLPeerDecryptError:
- failf(data, "A decryption error occurred");
- break;
- case errSSLBadCipherSuite:
- failf(data, "A bad SSL cipher suite was encountered");
- break;
- case errSSLCrypto:
- failf(data, "An underlying cryptographic error was encountered");
- break;
- #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
- case errSSLWeakPeerEphemeralDHKey:
- failf(data, "Indicates a weak ephemeral Diffie-Hellman key");
- break;
- #endif
- /* Problem with the message record validation */
- case errSSLBadRecordMac:
- case errSSLPeerBadRecordMac:
- failf(data, "A record with a bad message authentication code (MAC) "
- "was encountered");
- break;
- case errSSLRecordOverflow:
- case errSSLPeerRecordOverflow:
- failf(data, "A record overflow occurred");
- break;
- /* Problem with zlib decompression */
- case errSSLPeerDecompressFail:
- failf(data, "Decompression failed");
- break;
- /* Problem with access */
- case errSSLPeerAccessDenied:
- failf(data, "Access was denied");
- break;
- case errSSLPeerInsufficientSecurity:
- failf(data, "There is insufficient security for this operation");
- break;
- /* These are all certificate problems with the server: */
- case errSSLXCertChainInvalid:
- failf(data, "SSL certificate problem: Invalid certificate chain");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLUnknownRootCert:
- failf(data, "SSL certificate problem: Untrusted root certificate");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLNoRootCert:
- failf(data, "SSL certificate problem: No root certificate");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLCertNotYetValid:
- failf(data, "SSL certificate problem: The certificate chain had a "
- "certificate that is not yet valid");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLCertExpired:
- case errSSLPeerCertExpired:
- failf(data, "SSL certificate problem: Certificate chain had an "
- "expired certificate");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLBadCert:
- case errSSLPeerBadCert:
- failf(data, "SSL certificate problem: Couldn't understand the server "
- "certificate format");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLPeerUnsupportedCert:
- failf(data, "SSL certificate problem: An unsupported certificate "
- "format was encountered");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLPeerCertRevoked:
- failf(data, "SSL certificate problem: The certificate was revoked");
- return CURLE_PEER_FAILED_VERIFICATION;
- case errSSLPeerCertUnknown:
- failf(data, "SSL certificate problem: The certificate is unknown");
- return CURLE_PEER_FAILED_VERIFICATION;
- /* These are all certificate problems with the client: */
- case errSecAuthFailed:
- failf(data, "SSL authentication failed");
- break;
- case errSSLPeerHandshakeFail:
- failf(data, "SSL peer handshake failed, the server most likely "
- "requires a client certificate to connect");
- break;
- case errSSLPeerUnknownCA:
- failf(data, "SSL server rejected the client certificate due to "
- "the certificate being signed by an unknown certificate "
- "authority");
- break;
- /* 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;
- /* Problem with SSL / TLS negotiation */
- case errSSLNegotiation:
- failf(data, "Could not negotiate an SSL cipher suite with the server");
- break;
- case errSSLBadConfiguration:
- failf(data, "A configuration error occurred");
- break;
- case errSSLProtocol:
- failf(data, "SSL protocol error");
- break;
- case errSSLPeerProtocolVersion:
- failf(data, "A bad protocol version was encountered");
- break;
- case errSSLPeerNoRenegotiation:
- failf(data, "No renegotiation is allowed");
- break;
- /* Generic handshake errors: */
- case errSSLConnectionRefused:
- failf(data, "Server dropped the connection during the SSL handshake");
- break;
- case errSSLClosedAbort:
- failf(data, "Server aborted the SSL handshake");
- break;
- case errSSLClosedGraceful:
- failf(data, "The connection closed gracefully");
- break;
- case errSSLClosedNoNotify:
- failf(data, "The server closed the session with no notification");
- break;
- /* Sometimes paramErr happens with buggy ciphers: */
- case paramErr:
- case errSSLInternal:
- case errSSLPeerInternalError:
- failf(data, "Internal SSL engine error encountered during the "
- "SSL handshake");
- break;
- case errSSLFatalAlert:
- failf(data, "Fatal SSL engine error encountered during the SSL "
- "handshake");
- break;
- /* Unclassified error */
- case errSSLBufferOverflow:
- failf(data, "An insufficient buffer was provided");
- break;
- case errSSLIllegalParam:
- failf(data, "An illegal parameter was encountered");
- break;
- case errSSLModuleAttach:
- failf(data, "Module attach failure");
- break;
- case errSSLSessionNotFound:
- failf(data, "An attempt to restore an unknown session failed");
- break;
- case errSSLPeerExportRestriction:
- failf(data, "An export restriction occurred");
- break;
- case errSSLPeerUserCancelled:
- failf(data, "The user canceled the operation");
- break;
- case errSSLPeerUnexpectedMsg:
- failf(data, "Peer rejected unexpected message");
- break;
- #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
- /* Treaing non-fatal error as fatal like before */
- case errSSLClientHelloReceived:
- failf(data, "A non-fatal result for providing a server name "
- "indication");
- break;
- #endif
- /* Error codes defined in the enum but should never be returned.
- We list them here just in case. */
- #if CURL_BUILD_MAC_10_6
- /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */
- case errSSLClientCertRequested:
- failf(data, "The server has requested a client certificate");
- break;
- #endif
- #if CURL_BUILD_MAC_10_9
- /* Alias for errSSLLast, end of error range */
- case errSSLUnexpectedRecord:
- failf(data, "Unexpected (skipped) record in DTLS");
- break;
- #endif
- default:
- /* May also return codes listed in Security Framework Result Codes */
- failf(data, "Unknown SSL protocol error in connection to %s:%d",
- hostname, err);
- break;
- }
- return CURLE_SSL_CONNECT_ERROR;
- }
- else {
- /* we have been connected fine, we're not waiting for anything else. */
- connssl->connecting_state = ssl_connect_3;
- #ifdef SECTRANSP_PINNEDPUBKEY
- if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) {
- CURLcode result = pkp_pin_peer_pubkey(data, backend->ssl_ctx,
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
- if(result) {
- failf(data, "SSL: public key does not match pinned public key!");
- return result;
- }
- }
- #endif /* SECTRANSP_PINNEDPUBKEY */
- /* Informational message */
- (void)SSLGetNegotiatedCipher(backend->ssl_ctx, &cipher);
- (void)SSLGetNegotiatedProtocolVersion(backend->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 /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
- case kTLSProtocol13:
- infof(data, "TLS 1.3 connection using %s\n",
- TLSCipherNameForNumber(cipher));
- break;
- #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
- default:
- infof(data, "Unknown protocol connection\n");
- break;
- }
- #if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
- if(conn->bits.tls_enable_alpn) {
- if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
- CFArrayRef alpnArr = NULL;
- CFStringRef chosenProtocol = NULL;
- err = SSLCopyALPNProtocols(backend->ssl_ctx, &alpnArr);
- if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
- chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
- #ifdef USE_NGHTTP2
- if(chosenProtocol &&
- !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID),
- 0)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
- }
- else
- #endif
- if(chosenProtocol &&
- !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- }
- else
- infof(data, "ALPN, server did not agree to a protocol\n");
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
- /* chosenProtocol is a reference to the string within alpnArr
- and doesn't need to be freed separately */
- if(alpnArr)
- CFRelease(alpnArr);
- }
- }
- #endif
- return CURLE_OK;
- }
- }
- #ifndef CURL_DISABLE_VERBOSE_STRINGS
- /* This should be called during step3 of the connection at the earliest */
- static void
- show_verbose_server_cert(struct connectdata *conn,
- int sockindex)
- {
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- CFArrayRef server_certs = NULL;
- SecCertificateRef server_cert;
- OSStatus err;
- CFIndex i, count;
- SecTrustRef trust = NULL;
- if(!backend->ssl_ctx)
- return;
- #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
- #if CURL_BUILD_IOS
- #pragma unused(server_certs)
- err = SSLCopyPeerTrust(backend->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++) {
- CURLcode result;
- char *certp;
- server_cert = SecTrustGetCertificateAtIndex(trust, i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s\n", certp);
- free(certp);
- }
- }
- 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(backend->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++) {
- char *certp;
- CURLcode result;
- server_cert = SecTrustGetCertificateAtIndex(trust, i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s\n", certp);
- free(certp);
- }
- }
- CFRelease(trust);
- }
- }
- else {
- #if CURL_SUPPORT_MAC_10_8
- err = SSLCopyPeerCertificates(backend->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++) {
- char *certp;
- CURLcode result;
- server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
- i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s\n", certp);
- free(certp);
- }
- }
- CFRelease(server_certs);
- }
- #endif /* CURL_SUPPORT_MAC_10_8 */
- }
- #endif /* CURL_BUILD_IOS */
- #else
- #pragma unused(trust)
- err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
- if(err == noErr) {
- count = CFArrayGetCount(server_certs);
- for(i = 0L ; i < count ; i++) {
- CURLcode result;
- char *certp;
- server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s\n", certp);
- free(certp);
- }
- }
- CFRelease(server_certs);
- }
- #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
- }
- #endif /* !CURL_DISABLE_VERBOSE_STRINGS */
- static CURLcode
- sectransp_connect_step3(struct connectdata *conn,
- int sockindex)
- {
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- /* There is no step 3!
- * Well, okay, if verbose mode is on, let's print the details of the
- * server certificates. */
- #ifndef CURL_DISABLE_VERBOSE_STRINGS
- if(data->set.verbose)
- show_verbose_server_cert(conn, sockindex);
- #endif
- connssl->connecting_state = ssl_connect_done;
- return CURLE_OK;
- }
- static Curl_recv sectransp_recv;
- static Curl_send sectransp_send;
- static CURLcode
- sectransp_connect_common(struct connectdata *conn,
- int sockindex,
- bool nonblocking,
- bool *done)
- {
- CURLcode result;
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- curl_socket_t sockfd = conn->sock[sockindex];
- 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 */
- const timediff_t 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;
- }
- result = sectransp_connect_step1(conn, sockindex);
- if(result)
- return result;
- }
- 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 */
- const timediff_t 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_check(readfd, CURL_SOCKET_BAD, 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.
- */
- result = sectransp_connect_step2(conn, sockindex);
- if(result || (nonblocking &&
- (ssl_connect_2 == connssl->connecting_state ||
- ssl_connect_2_reading == connssl->connecting_state ||
- ssl_connect_2_writing == connssl->connecting_state)))
- return result;
- } /* repeat step2 until all transactions are done. */
- if(ssl_connect_3 == connssl->connecting_state) {
- result = sectransp_connect_step3(conn, sockindex);
- if(result)
- return result;
- }
- if(ssl_connect_done == connssl->connecting_state) {
- connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = sectransp_recv;
- conn->send[sockindex] = sectransp_send;
- *done = TRUE;
- }
- else
- *done = FALSE;
- /* Reset our connect state machine */
- connssl->connecting_state = ssl_connect_1;
- return CURLE_OK;
- }
- static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
- {
- return sectransp_connect_common(conn, sockindex, TRUE, done);
- }
- static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex)
- {
- CURLcode result;
- bool done = FALSE;
- result = sectransp_connect_common(conn, sockindex, FALSE, &done);
- if(result)
- return result;
- DEBUGASSERT(done);
- return CURLE_OK;
- }
- static void Curl_sectransp_close(struct connectdata *conn, int sockindex)
- {
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- if(backend->ssl_ctx) {
- (void)SSLClose(backend->ssl_ctx);
- #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- if(SSLCreateContext != NULL)
- CFRelease(backend->ssl_ctx);
- #if CURL_SUPPORT_MAC_10_8
- else
- (void)SSLDisposeContext(backend->ssl_ctx);
- #endif /* CURL_SUPPORT_MAC_10_8 */
- #else
- (void)SSLDisposeContext(backend->ssl_ctx);
- #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
- backend->ssl_ctx = NULL;
- }
- backend->ssl_sockfd = 0;
- }
- static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex)
- {
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- struct Curl_easy *data = conn->data;
- ssize_t nread;
- int what;
- int rc;
- char buf[120];
- if(!backend->ssl_ctx)
- return 0;
- #ifndef CURL_DISABLE_FTP
- if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
- return 0;
- #endif
- Curl_sectransp_close(conn, sockindex);
- rc = 0;
- what = SOCKET_READABLE(conn->sock[sockindex], 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 = SOCKET_READABLE(conn->sock[sockindex], 0);
- }
- return rc;
- }
- static void Curl_sectransp_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 sectransp_connect_step1... */
- Curl_safefree(ptr);
- }
- static size_t Curl_sectransp_version(char *buffer, size_t size)
- {
- return msnprintf(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
- */
- static int Curl_sectransp_check_cxn(struct connectdata *conn)
- {
- struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
- struct ssl_backend_data *backend = connssl->backend;
- OSStatus err;
- SSLSessionState state;
- if(backend->ssl_ctx) {
- err = SSLGetSessionState(backend->ssl_ctx, &state);
- if(err == noErr)
- return state == kSSLConnected || state == kSSLHandshake;
- return -1;
- }
- return 0;
- }
- static bool Curl_sectransp_data_pending(const struct connectdata *conn,
- int connindex)
- {
- const struct ssl_connect_data *connssl = &conn->ssl[connindex];
- struct ssl_backend_data *backend = connssl->backend;
- OSStatus err;
- size_t buffer;
- if(backend->ssl_ctx) { /* SSL is in use */
- err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
- if(err == noErr)
- return buffer > 0UL;
- return false;
- }
- else
- return false;
- }
- static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM,
- 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;
- (void)data;
- 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;
- return CURLE_OK;
- }
- static CURLcode Curl_sectransp_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);
- return CURLE_OK;
- }
- static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
- {
- assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
- (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
- return CURLE_OK;
- }
- static bool Curl_sectransp_false_start(void)
- {
- #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
- if(SSLSetSessionOption != NULL)
- return TRUE;
- #endif
- return FALSE;
- }
- static ssize_t sectransp_send(struct connectdata *conn,
- int sockindex,
- const void *mem,
- size_t len,
- CURLcode *curlcode)
- {
- /*struct Curl_easy *data = conn->data;*/
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- 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(backend->ssl_write_buffered_length) {
- /* Write the buffered data: */
- err = SSLWrite(backend->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 = backend->ssl_write_buffered_length;
- backend->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(backend->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 */
- backend->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 sectransp_recv(struct connectdata *conn,
- int num,
- char *buf,
- size_t buffersize,
- CURLcode *curlcode)
- {
- /*struct Curl_easy *data = conn->data;*/
- struct ssl_connect_data *connssl = &conn->ssl[num];
- struct ssl_backend_data *backend = connssl->backend;
- size_t processed = 0UL;
- OSStatus err;
- again:
- err = SSLRead(backend->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;
- /* The below is errSSLPeerAuthCompleted; it's not defined in
- Leopard's headers */
- case -9841:
- if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
- CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), conn->data,
- backend->ssl_ctx);
- if(result)
- return result;
- }
- goto again;
- default:
- failf(conn->data, "SSLRead() return error %d", err);
- *curlcode = CURLE_RECV_ERROR;
- return -1L;
- break;
- }
- }
- return (ssize_t)processed;
- }
- static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
- {
- struct ssl_backend_data *backend = connssl->backend;
- (void)info;
- return backend->ssl_ctx;
- }
- const struct Curl_ssl Curl_ssl_sectransp = {
- { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */
- #ifdef SECTRANSP_PINNEDPUBKEY
- SSLSUPP_PINNEDPUBKEY,
- #else
- 0,
- #endif /* SECTRANSP_PINNEDPUBKEY */
- sizeof(struct ssl_backend_data),
- Curl_none_init, /* init */
- Curl_none_cleanup, /* cleanup */
- Curl_sectransp_version, /* version */
- Curl_sectransp_check_cxn, /* check_cxn */
- Curl_sectransp_shutdown, /* shutdown */
- Curl_sectransp_data_pending, /* data_pending */
- Curl_sectransp_random, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
- Curl_sectransp_connect, /* connect */
- Curl_sectransp_connect_nonblocking, /* connect_nonblocking */
- Curl_sectransp_get_internals, /* get_internals */
- Curl_sectransp_close, /* close_one */
- Curl_none_close_all, /* close_all */
- Curl_sectransp_session_free, /* session_free */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- Curl_sectransp_false_start, /* false_start */
- Curl_sectransp_md5sum, /* md5sum */
- Curl_sectransp_sha256sum /* sha256sum */
- };
- #ifdef __clang__
- #pragma clang diagnostic pop
- #endif
- #endif /* USE_SECTRANSP */
|