vtls.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.haxx.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. ***************************************************************************/
  22. /* This file is for implementing all "generic" SSL functions that all libcurl
  23. internals should use. It is then responsible for calling the proper
  24. "backend" function.
  25. SSL-functions in libcurl should call functions in this source file, and not
  26. to any specific SSL-layer.
  27. Curl_ssl_ - prefix for generic ones
  28. Note that this source code uses the functions of the configured SSL
  29. backend via the global Curl_ssl instance.
  30. "SSL/TLS Strong Encryption: An Introduction"
  31. https://httpd.apache.org/docs/2.0/ssl/ssl_intro.html
  32. */
  33. #include "curl_setup.h"
  34. #ifdef HAVE_SYS_TYPES_H
  35. #include <sys/types.h>
  36. #endif
  37. #ifdef HAVE_SYS_STAT_H
  38. #include <sys/stat.h>
  39. #endif
  40. #ifdef HAVE_FCNTL_H
  41. #include <fcntl.h>
  42. #endif
  43. #include "urldata.h"
  44. #include "vtls.h" /* generic SSL protos etc */
  45. #include "slist.h"
  46. #include "sendf.h"
  47. #include "strcase.h"
  48. #include "url.h"
  49. #include "progress.h"
  50. #include "share.h"
  51. #include "multiif.h"
  52. #include "timeval.h"
  53. #include "curl_md5.h"
  54. #include "warnless.h"
  55. #include "curl_base64.h"
  56. #include "curl_printf.h"
  57. /* The last #include files should be: */
  58. #include "curl_memory.h"
  59. #include "memdebug.h"
  60. /* convenience macro to check if this handle is using a shared SSL session */
  61. #define SSLSESSION_SHARED(data) (data->share && \
  62. (data->share->specifier & \
  63. (1<<CURL_LOCK_DATA_SSL_SESSION)))
  64. #define CLONE_STRING(var) \
  65. if(source->var) { \
  66. dest->var = strdup(source->var); \
  67. if(!dest->var) \
  68. return FALSE; \
  69. } \
  70. else \
  71. dest->var = NULL;
  72. bool
  73. Curl_ssl_config_matches(struct ssl_primary_config* data,
  74. struct ssl_primary_config* needle)
  75. {
  76. if((data->version == needle->version) &&
  77. (data->version_max == needle->version_max) &&
  78. (data->verifypeer == needle->verifypeer) &&
  79. (data->verifyhost == needle->verifyhost) &&
  80. (data->verifystatus == needle->verifystatus) &&
  81. Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
  82. Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
  83. Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
  84. Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
  85. Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
  86. Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
  87. Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
  88. Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key))
  89. return TRUE;
  90. return FALSE;
  91. }
  92. bool
  93. Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
  94. struct ssl_primary_config *dest)
  95. {
  96. dest->version = source->version;
  97. dest->version_max = source->version_max;
  98. dest->verifypeer = source->verifypeer;
  99. dest->verifyhost = source->verifyhost;
  100. dest->verifystatus = source->verifystatus;
  101. dest->sessionid = source->sessionid;
  102. CLONE_STRING(CApath);
  103. CLONE_STRING(CAfile);
  104. CLONE_STRING(clientcert);
  105. CLONE_STRING(random_file);
  106. CLONE_STRING(egdsocket);
  107. CLONE_STRING(cipher_list);
  108. CLONE_STRING(cipher_list13);
  109. CLONE_STRING(pinned_key);
  110. return TRUE;
  111. }
  112. void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
  113. {
  114. Curl_safefree(sslc->CApath);
  115. Curl_safefree(sslc->CAfile);
  116. Curl_safefree(sslc->clientcert);
  117. Curl_safefree(sslc->random_file);
  118. Curl_safefree(sslc->egdsocket);
  119. Curl_safefree(sslc->cipher_list);
  120. Curl_safefree(sslc->cipher_list13);
  121. Curl_safefree(sslc->pinned_key);
  122. }
  123. #ifdef USE_SSL
  124. static int multissl_init(const struct Curl_ssl *backend);
  125. #endif
  126. int Curl_ssl_backend(void)
  127. {
  128. #ifdef USE_SSL
  129. multissl_init(NULL);
  130. return Curl_ssl->info.id;
  131. #else
  132. return (int)CURLSSLBACKEND_NONE;
  133. #endif
  134. }
  135. #ifdef USE_SSL
  136. /* "global" init done? */
  137. static bool init_ssl = FALSE;
  138. /**
  139. * Global SSL init
  140. *
  141. * @retval 0 error initializing SSL
  142. * @retval 1 SSL initialized successfully
  143. */
  144. int Curl_ssl_init(void)
  145. {
  146. /* make sure this is only done once */
  147. if(init_ssl)
  148. return 1;
  149. init_ssl = TRUE; /* never again */
  150. return Curl_ssl->init();
  151. }
  152. /* Global cleanup */
  153. void Curl_ssl_cleanup(void)
  154. {
  155. if(init_ssl) {
  156. /* only cleanup if we did a previous init */
  157. Curl_ssl->cleanup();
  158. init_ssl = FALSE;
  159. }
  160. }
  161. static bool ssl_prefs_check(struct Curl_easy *data)
  162. {
  163. /* check for CURLOPT_SSLVERSION invalid parameter value */
  164. const long sslver = data->set.ssl.primary.version;
  165. if((sslver < 0) || (sslver >= CURL_SSLVERSION_LAST)) {
  166. failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
  167. return FALSE;
  168. }
  169. switch(data->set.ssl.primary.version_max) {
  170. case CURL_SSLVERSION_MAX_NONE:
  171. case CURL_SSLVERSION_MAX_DEFAULT:
  172. break;
  173. default:
  174. if((data->set.ssl.primary.version_max >> 16) < sslver) {
  175. failf(data, "CURL_SSLVERSION_MAX incompatible with CURL_SSLVERSION");
  176. return FALSE;
  177. }
  178. }
  179. return TRUE;
  180. }
  181. static CURLcode
  182. ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
  183. {
  184. DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
  185. if(ssl_connection_complete == conn->ssl[sockindex].state &&
  186. !conn->proxy_ssl[sockindex].use) {
  187. struct ssl_backend_data *pbdata;
  188. if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
  189. return CURLE_NOT_BUILT_IN;
  190. /* The pointers to the ssl backend data, which is opaque here, are swapped
  191. rather than move the contents. */
  192. pbdata = conn->proxy_ssl[sockindex].backend;
  193. conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
  194. memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
  195. memset(pbdata, 0, Curl_ssl->sizeof_ssl_backend_data);
  196. conn->ssl[sockindex].backend = pbdata;
  197. }
  198. return CURLE_OK;
  199. }
  200. CURLcode
  201. Curl_ssl_connect(struct connectdata *conn, int sockindex)
  202. {
  203. CURLcode result;
  204. if(conn->bits.proxy_ssl_connected[sockindex]) {
  205. result = ssl_connect_init_proxy(conn, sockindex);
  206. if(result)
  207. return result;
  208. }
  209. if(!ssl_prefs_check(conn->data))
  210. return CURLE_SSL_CONNECT_ERROR;
  211. /* mark this is being ssl-enabled from here on. */
  212. conn->ssl[sockindex].use = TRUE;
  213. conn->ssl[sockindex].state = ssl_connection_negotiating;
  214. result = Curl_ssl->connect_blocking(conn, sockindex);
  215. if(!result)
  216. Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
  217. return result;
  218. }
  219. CURLcode
  220. Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
  221. bool *done)
  222. {
  223. CURLcode result;
  224. if(conn->bits.proxy_ssl_connected[sockindex]) {
  225. result = ssl_connect_init_proxy(conn, sockindex);
  226. if(result)
  227. return result;
  228. }
  229. if(!ssl_prefs_check(conn->data))
  230. return CURLE_SSL_CONNECT_ERROR;
  231. /* mark this is being ssl requested from here on. */
  232. conn->ssl[sockindex].use = TRUE;
  233. result = Curl_ssl->connect_nonblocking(conn, sockindex, done);
  234. if(!result && *done)
  235. Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
  236. return result;
  237. }
  238. /*
  239. * Lock shared SSL session data
  240. */
  241. void Curl_ssl_sessionid_lock(struct connectdata *conn)
  242. {
  243. if(SSLSESSION_SHARED(conn->data))
  244. Curl_share_lock(conn->data,
  245. CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
  246. }
  247. /*
  248. * Unlock shared SSL session data
  249. */
  250. void Curl_ssl_sessionid_unlock(struct connectdata *conn)
  251. {
  252. if(SSLSESSION_SHARED(conn->data))
  253. Curl_share_unlock(conn->data, CURL_LOCK_DATA_SSL_SESSION);
  254. }
  255. /*
  256. * Check if there's a session ID for the given connection in the cache, and if
  257. * there's one suitable, it is provided. Returns TRUE when no entry matched.
  258. */
  259. bool Curl_ssl_getsessionid(struct connectdata *conn,
  260. void **ssl_sessionid,
  261. size_t *idsize, /* set 0 if unknown */
  262. int sockindex)
  263. {
  264. struct curl_ssl_session *check;
  265. struct Curl_easy *data = conn->data;
  266. size_t i;
  267. long *general_age;
  268. bool no_match = TRUE;
  269. const bool isProxy = CONNECT_PROXY_SSL();
  270. struct ssl_primary_config * const ssl_config = isProxy ?
  271. &conn->proxy_ssl_config :
  272. &conn->ssl_config;
  273. const char * const name = isProxy ? conn->http_proxy.host.name :
  274. conn->host.name;
  275. int port = isProxy ? (int)conn->port : conn->remote_port;
  276. *ssl_sessionid = NULL;
  277. DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
  278. if(!SSL_SET_OPTION(primary.sessionid))
  279. /* session ID re-use is disabled */
  280. return TRUE;
  281. /* Lock if shared */
  282. if(SSLSESSION_SHARED(data))
  283. general_age = &data->share->sessionage;
  284. else
  285. general_age = &data->state.sessionage;
  286. for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
  287. check = &data->state.session[i];
  288. if(!check->sessionid)
  289. /* not session ID means blank entry */
  290. continue;
  291. if(strcasecompare(name, check->name) &&
  292. ((!conn->bits.conn_to_host && !check->conn_to_host) ||
  293. (conn->bits.conn_to_host && check->conn_to_host &&
  294. strcasecompare(conn->conn_to_host.name, check->conn_to_host))) &&
  295. ((!conn->bits.conn_to_port && check->conn_to_port == -1) ||
  296. (conn->bits.conn_to_port && check->conn_to_port != -1 &&
  297. conn->conn_to_port == check->conn_to_port)) &&
  298. (port == check->remote_port) &&
  299. strcasecompare(conn->handler->scheme, check->scheme) &&
  300. Curl_ssl_config_matches(ssl_config, &check->ssl_config)) {
  301. /* yes, we have a session ID! */
  302. (*general_age)++; /* increase general age */
  303. check->age = *general_age; /* set this as used in this age */
  304. *ssl_sessionid = check->sessionid;
  305. if(idsize)
  306. *idsize = check->idsize;
  307. no_match = FALSE;
  308. break;
  309. }
  310. }
  311. return no_match;
  312. }
  313. /*
  314. * Kill a single session ID entry in the cache.
  315. */
  316. void Curl_ssl_kill_session(struct curl_ssl_session *session)
  317. {
  318. if(session->sessionid) {
  319. /* defensive check */
  320. /* free the ID the SSL-layer specific way */
  321. Curl_ssl->session_free(session->sessionid);
  322. session->sessionid = NULL;
  323. session->age = 0; /* fresh */
  324. Curl_free_primary_ssl_config(&session->ssl_config);
  325. Curl_safefree(session->name);
  326. Curl_safefree(session->conn_to_host);
  327. }
  328. }
  329. /*
  330. * Delete the given session ID from the cache.
  331. */
  332. void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
  333. {
  334. size_t i;
  335. struct Curl_easy *data = conn->data;
  336. for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
  337. struct curl_ssl_session *check = &data->state.session[i];
  338. if(check->sessionid == ssl_sessionid) {
  339. Curl_ssl_kill_session(check);
  340. break;
  341. }
  342. }
  343. }
  344. /*
  345. * Store session id in the session cache. The ID passed on to this function
  346. * must already have been extracted and allocated the proper way for the SSL
  347. * layer. Curl_XXXX_session_free() will be called to free/kill the session ID
  348. * later on.
  349. */
  350. CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
  351. void *ssl_sessionid,
  352. size_t idsize,
  353. int sockindex)
  354. {
  355. size_t i;
  356. struct Curl_easy *data = conn->data; /* the mother of all structs */
  357. struct curl_ssl_session *store = &data->state.session[0];
  358. long oldest_age = data->state.session[0].age; /* zero if unused */
  359. char *clone_host;
  360. char *clone_conn_to_host;
  361. int conn_to_port;
  362. long *general_age;
  363. const bool isProxy = CONNECT_PROXY_SSL();
  364. struct ssl_primary_config * const ssl_config = isProxy ?
  365. &conn->proxy_ssl_config :
  366. &conn->ssl_config;
  367. DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
  368. clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name);
  369. if(!clone_host)
  370. return CURLE_OUT_OF_MEMORY; /* bail out */
  371. if(conn->bits.conn_to_host) {
  372. clone_conn_to_host = strdup(conn->conn_to_host.name);
  373. if(!clone_conn_to_host) {
  374. free(clone_host);
  375. return CURLE_OUT_OF_MEMORY; /* bail out */
  376. }
  377. }
  378. else
  379. clone_conn_to_host = NULL;
  380. if(conn->bits.conn_to_port)
  381. conn_to_port = conn->conn_to_port;
  382. else
  383. conn_to_port = -1;
  384. /* Now we should add the session ID and the host name to the cache, (remove
  385. the oldest if necessary) */
  386. /* If using shared SSL session, lock! */
  387. if(SSLSESSION_SHARED(data)) {
  388. general_age = &data->share->sessionage;
  389. }
  390. else {
  391. general_age = &data->state.sessionage;
  392. }
  393. /* find an empty slot for us, or find the oldest */
  394. for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) &&
  395. data->state.session[i].sessionid; i++) {
  396. if(data->state.session[i].age < oldest_age) {
  397. oldest_age = data->state.session[i].age;
  398. store = &data->state.session[i];
  399. }
  400. }
  401. if(i == data->set.general_ssl.max_ssl_sessions)
  402. /* cache is full, we must "kill" the oldest entry! */
  403. Curl_ssl_kill_session(store);
  404. else
  405. store = &data->state.session[i]; /* use this slot */
  406. /* now init the session struct wisely */
  407. store->sessionid = ssl_sessionid;
  408. store->idsize = idsize;
  409. store->age = *general_age; /* set current age */
  410. /* free it if there's one already present */
  411. free(store->name);
  412. free(store->conn_to_host);
  413. store->name = clone_host; /* clone host name */
  414. store->conn_to_host = clone_conn_to_host; /* clone connect to host name */
  415. store->conn_to_port = conn_to_port; /* connect to port number */
  416. /* port number */
  417. store->remote_port = isProxy ? (int)conn->port : conn->remote_port;
  418. store->scheme = conn->handler->scheme;
  419. if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) {
  420. store->sessionid = NULL; /* let caller free sessionid */
  421. free(clone_host);
  422. free(clone_conn_to_host);
  423. return CURLE_OUT_OF_MEMORY;
  424. }
  425. return CURLE_OK;
  426. }
  427. void Curl_ssl_close_all(struct Curl_easy *data)
  428. {
  429. /* kill the session ID cache if not shared */
  430. if(data->state.session && !SSLSESSION_SHARED(data)) {
  431. size_t i;
  432. for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++)
  433. /* the single-killer function handles empty table slots */
  434. Curl_ssl_kill_session(&data->state.session[i]);
  435. /* free the cache data */
  436. Curl_safefree(data->state.session);
  437. }
  438. Curl_ssl->close_all(data);
  439. }
  440. #if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
  441. defined(USE_SECTRANSP) || defined(USE_POLARSSL) || defined(USE_NSS) || \
  442. defined(USE_MBEDTLS) || defined(USE_WOLFSSL) || defined(USE_BEARSSL)
  443. int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks)
  444. {
  445. struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
  446. if(connssl->connecting_state == ssl_connect_2_writing) {
  447. /* write mode */
  448. socks[0] = conn->sock[FIRSTSOCKET];
  449. return GETSOCK_WRITESOCK(0);
  450. }
  451. if(connssl->connecting_state == ssl_connect_2_reading) {
  452. /* read mode */
  453. socks[0] = conn->sock[FIRSTSOCKET];
  454. return GETSOCK_READSOCK(0);
  455. }
  456. return GETSOCK_BLANK;
  457. }
  458. #else
  459. int Curl_ssl_getsock(struct connectdata *conn,
  460. curl_socket_t *socks)
  461. {
  462. (void)conn;
  463. (void)socks;
  464. return GETSOCK_BLANK;
  465. }
  466. /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */
  467. #endif
  468. void Curl_ssl_close(struct connectdata *conn, int sockindex)
  469. {
  470. DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
  471. Curl_ssl->close_one(conn, sockindex);
  472. }
  473. CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
  474. {
  475. if(Curl_ssl->shut_down(conn, sockindex))
  476. return CURLE_SSL_SHUTDOWN_FAILED;
  477. conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
  478. conn->ssl[sockindex].state = ssl_connection_none;
  479. conn->recv[sockindex] = Curl_recv_plain;
  480. conn->send[sockindex] = Curl_send_plain;
  481. return CURLE_OK;
  482. }
  483. /* Selects an SSL crypto engine
  484. */
  485. CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine)
  486. {
  487. return Curl_ssl->set_engine(data, engine);
  488. }
  489. /* Selects the default SSL crypto engine
  490. */
  491. CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data)
  492. {
  493. return Curl_ssl->set_engine_default(data);
  494. }
  495. /* Return list of OpenSSL crypto engine names. */
  496. struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data)
  497. {
  498. return Curl_ssl->engines_list(data);
  499. }
  500. /*
  501. * This sets up a session ID cache to the specified size. Make sure this code
  502. * is agnostic to what underlying SSL technology we use.
  503. */
  504. CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
  505. {
  506. struct curl_ssl_session *session;
  507. if(data->state.session)
  508. /* this is just a precaution to prevent multiple inits */
  509. return CURLE_OK;
  510. session = calloc(amount, sizeof(struct curl_ssl_session));
  511. if(!session)
  512. return CURLE_OUT_OF_MEMORY;
  513. /* store the info in the SSL section */
  514. data->set.general_ssl.max_ssl_sessions = amount;
  515. data->state.session = session;
  516. data->state.sessionage = 1; /* this is brand new */
  517. return CURLE_OK;
  518. }
  519. static size_t Curl_multissl_version(char *buffer, size_t size);
  520. size_t Curl_ssl_version(char *buffer, size_t size)
  521. {
  522. #ifdef CURL_WITH_MULTI_SSL
  523. return Curl_multissl_version(buffer, size);
  524. #else
  525. return Curl_ssl->version(buffer, size);
  526. #endif
  527. }
  528. /*
  529. * This function tries to determine connection status.
  530. *
  531. * Return codes:
  532. * 1 means the connection is still in place
  533. * 0 means the connection has been closed
  534. * -1 means the connection status is unknown
  535. */
  536. int Curl_ssl_check_cxn(struct connectdata *conn)
  537. {
  538. return Curl_ssl->check_cxn(conn);
  539. }
  540. bool Curl_ssl_data_pending(const struct connectdata *conn,
  541. int connindex)
  542. {
  543. return Curl_ssl->data_pending(conn, connindex);
  544. }
  545. void Curl_ssl_free_certinfo(struct Curl_easy *data)
  546. {
  547. struct curl_certinfo *ci = &data->info.certs;
  548. if(ci->num_of_certs) {
  549. /* free all individual lists used */
  550. int i;
  551. for(i = 0; i<ci->num_of_certs; i++) {
  552. curl_slist_free_all(ci->certinfo[i]);
  553. ci->certinfo[i] = NULL;
  554. }
  555. free(ci->certinfo); /* free the actual array too */
  556. ci->certinfo = NULL;
  557. ci->num_of_certs = 0;
  558. }
  559. }
  560. CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num)
  561. {
  562. struct curl_certinfo *ci = &data->info.certs;
  563. struct curl_slist **table;
  564. /* Free any previous certificate information structures */
  565. Curl_ssl_free_certinfo(data);
  566. /* Allocate the required certificate information structures */
  567. table = calloc((size_t) num, sizeof(struct curl_slist *));
  568. if(!table)
  569. return CURLE_OUT_OF_MEMORY;
  570. ci->num_of_certs = num;
  571. ci->certinfo = table;
  572. return CURLE_OK;
  573. }
  574. /*
  575. * 'value' is NOT a zero terminated string
  576. */
  577. CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
  578. int certnum,
  579. const char *label,
  580. const char *value,
  581. size_t valuelen)
  582. {
  583. struct curl_certinfo *ci = &data->info.certs;
  584. char *output;
  585. struct curl_slist *nl;
  586. CURLcode result = CURLE_OK;
  587. size_t labellen = strlen(label);
  588. size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
  589. output = malloc(outlen);
  590. if(!output)
  591. return CURLE_OUT_OF_MEMORY;
  592. /* sprintf the label and colon */
  593. msnprintf(output, outlen, "%s:", label);
  594. /* memcpy the value (it might not be zero terminated) */
  595. memcpy(&output[labellen + 1], value, valuelen);
  596. /* zero terminate the output */
  597. output[labellen + 1 + valuelen] = 0;
  598. nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
  599. if(!nl) {
  600. free(output);
  601. curl_slist_free_all(ci->certinfo[certnum]);
  602. result = CURLE_OUT_OF_MEMORY;
  603. }
  604. ci->certinfo[certnum] = nl;
  605. return result;
  606. }
  607. /*
  608. * This is a convenience function for push_certinfo_len that takes a zero
  609. * terminated value.
  610. */
  611. CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data,
  612. int certnum,
  613. const char *label,
  614. const char *value)
  615. {
  616. size_t valuelen = strlen(value);
  617. return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
  618. }
  619. CURLcode Curl_ssl_random(struct Curl_easy *data,
  620. unsigned char *entropy,
  621. size_t length)
  622. {
  623. return Curl_ssl->random(data, entropy, length);
  624. }
  625. /*
  626. * Public key pem to der conversion
  627. */
  628. static CURLcode pubkey_pem_to_der(const char *pem,
  629. unsigned char **der, size_t *der_len)
  630. {
  631. char *stripped_pem, *begin_pos, *end_pos;
  632. size_t pem_count, stripped_pem_count = 0, pem_len;
  633. CURLcode result;
  634. /* if no pem, exit. */
  635. if(!pem)
  636. return CURLE_BAD_CONTENT_ENCODING;
  637. begin_pos = strstr(pem, "-----BEGIN PUBLIC KEY-----");
  638. if(!begin_pos)
  639. return CURLE_BAD_CONTENT_ENCODING;
  640. pem_count = begin_pos - pem;
  641. /* Invalid if not at beginning AND not directly following \n */
  642. if(0 != pem_count && '\n' != pem[pem_count - 1])
  643. return CURLE_BAD_CONTENT_ENCODING;
  644. /* 26 is length of "-----BEGIN PUBLIC KEY-----" */
  645. pem_count += 26;
  646. /* Invalid if not directly following \n */
  647. end_pos = strstr(pem + pem_count, "\n-----END PUBLIC KEY-----");
  648. if(!end_pos)
  649. return CURLE_BAD_CONTENT_ENCODING;
  650. pem_len = end_pos - pem;
  651. stripped_pem = malloc(pem_len - pem_count + 1);
  652. if(!stripped_pem)
  653. return CURLE_OUT_OF_MEMORY;
  654. /*
  655. * Here we loop through the pem array one character at a time between the
  656. * correct indices, and place each character that is not '\n' or '\r'
  657. * into the stripped_pem array, which should represent the raw base64 string
  658. */
  659. while(pem_count < pem_len) {
  660. if('\n' != pem[pem_count] && '\r' != pem[pem_count])
  661. stripped_pem[stripped_pem_count++] = pem[pem_count];
  662. ++pem_count;
  663. }
  664. /* Place the null terminator in the correct place */
  665. stripped_pem[stripped_pem_count] = '\0';
  666. result = Curl_base64_decode(stripped_pem, der, der_len);
  667. Curl_safefree(stripped_pem);
  668. return result;
  669. }
  670. /*
  671. * Generic pinned public key check.
  672. */
  673. CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
  674. const char *pinnedpubkey,
  675. const unsigned char *pubkey, size_t pubkeylen)
  676. {
  677. FILE *fp;
  678. unsigned char *buf = NULL, *pem_ptr = NULL;
  679. CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
  680. /* if a path wasn't specified, don't pin */
  681. if(!pinnedpubkey)
  682. return CURLE_OK;
  683. if(!pubkey || !pubkeylen)
  684. return result;
  685. /* only do this if pinnedpubkey starts with "sha256//", length 8 */
  686. if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
  687. CURLcode encode;
  688. size_t encodedlen, pinkeylen;
  689. char *encoded, *pinkeycopy, *begin_pos, *end_pos;
  690. unsigned char *sha256sumdigest;
  691. if(!Curl_ssl->sha256sum) {
  692. /* without sha256 support, this cannot match */
  693. return result;
  694. }
  695. /* compute sha256sum of public key */
  696. sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH);
  697. if(!sha256sumdigest)
  698. return CURLE_OUT_OF_MEMORY;
  699. encode = Curl_ssl->sha256sum(pubkey, pubkeylen,
  700. sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
  701. if(encode != CURLE_OK)
  702. return encode;
  703. encode = Curl_base64_encode(data, (char *)sha256sumdigest,
  704. CURL_SHA256_DIGEST_LENGTH, &encoded,
  705. &encodedlen);
  706. Curl_safefree(sha256sumdigest);
  707. if(encode)
  708. return encode;
  709. infof(data, "\t public key hash: sha256//%s\n", encoded);
  710. /* it starts with sha256//, copy so we can modify it */
  711. pinkeylen = strlen(pinnedpubkey) + 1;
  712. pinkeycopy = malloc(pinkeylen);
  713. if(!pinkeycopy) {
  714. Curl_safefree(encoded);
  715. return CURLE_OUT_OF_MEMORY;
  716. }
  717. memcpy(pinkeycopy, pinnedpubkey, pinkeylen);
  718. /* point begin_pos to the copy, and start extracting keys */
  719. begin_pos = pinkeycopy;
  720. do {
  721. end_pos = strstr(begin_pos, ";sha256//");
  722. /*
  723. * if there is an end_pos, null terminate,
  724. * otherwise it'll go to the end of the original string
  725. */
  726. if(end_pos)
  727. end_pos[0] = '\0';
  728. /* compare base64 sha256 digests, 8 is the length of "sha256//" */
  729. if(encodedlen == strlen(begin_pos + 8) &&
  730. !memcmp(encoded, begin_pos + 8, encodedlen)) {
  731. result = CURLE_OK;
  732. break;
  733. }
  734. /*
  735. * change back the null-terminator we changed earlier,
  736. * and look for next begin
  737. */
  738. if(end_pos) {
  739. end_pos[0] = ';';
  740. begin_pos = strstr(end_pos, "sha256//");
  741. }
  742. } while(end_pos && begin_pos);
  743. Curl_safefree(encoded);
  744. Curl_safefree(pinkeycopy);
  745. return result;
  746. }
  747. fp = fopen(pinnedpubkey, "rb");
  748. if(!fp)
  749. return result;
  750. do {
  751. long filesize;
  752. size_t size, pem_len;
  753. CURLcode pem_read;
  754. /* Determine the file's size */
  755. if(fseek(fp, 0, SEEK_END))
  756. break;
  757. filesize = ftell(fp);
  758. if(fseek(fp, 0, SEEK_SET))
  759. break;
  760. if(filesize < 0 || filesize > MAX_PINNED_PUBKEY_SIZE)
  761. break;
  762. /*
  763. * if the size of our certificate is bigger than the file
  764. * size then it can't match
  765. */
  766. size = curlx_sotouz((curl_off_t) filesize);
  767. if(pubkeylen > size)
  768. break;
  769. /*
  770. * Allocate buffer for the pinned key
  771. * With 1 additional byte for null terminator in case of PEM key
  772. */
  773. buf = malloc(size + 1);
  774. if(!buf)
  775. break;
  776. /* Returns number of elements read, which should be 1 */
  777. if((int) fread(buf, size, 1, fp) != 1)
  778. break;
  779. /* If the sizes are the same, it can't be base64 encoded, must be der */
  780. if(pubkeylen == size) {
  781. if(!memcmp(pubkey, buf, pubkeylen))
  782. result = CURLE_OK;
  783. break;
  784. }
  785. /*
  786. * Otherwise we will assume it's PEM and try to decode it
  787. * after placing null terminator
  788. */
  789. buf[size] = '\0';
  790. pem_read = pubkey_pem_to_der((const char *)buf, &pem_ptr, &pem_len);
  791. /* if it wasn't read successfully, exit */
  792. if(pem_read)
  793. break;
  794. /*
  795. * if the size of our certificate doesn't match the size of
  796. * the decoded file, they can't be the same, otherwise compare
  797. */
  798. if(pubkeylen == pem_len && !memcmp(pubkey, pem_ptr, pubkeylen))
  799. result = CURLE_OK;
  800. } while(0);
  801. Curl_safefree(buf);
  802. Curl_safefree(pem_ptr);
  803. fclose(fp);
  804. return result;
  805. }
  806. #ifndef CURL_DISABLE_CRYPTO_AUTH
  807. CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
  808. size_t tmplen,
  809. unsigned char *md5sum, /* output */
  810. size_t md5len)
  811. {
  812. return Curl_ssl->md5sum(tmp, tmplen, md5sum, md5len);
  813. }
  814. #endif
  815. /*
  816. * Check whether the SSL backend supports the status_request extension.
  817. */
  818. bool Curl_ssl_cert_status_request(void)
  819. {
  820. return Curl_ssl->cert_status_request();
  821. }
  822. /*
  823. * Check whether the SSL backend supports false start.
  824. */
  825. bool Curl_ssl_false_start(void)
  826. {
  827. return Curl_ssl->false_start();
  828. }
  829. /*
  830. * Check whether the SSL backend supports setting TLS 1.3 cipher suites
  831. */
  832. bool Curl_ssl_tls13_ciphersuites(void)
  833. {
  834. return Curl_ssl->supports & SSLSUPP_TLS13_CIPHERSUITES;
  835. }
  836. /*
  837. * Default implementations for unsupported functions.
  838. */
  839. int Curl_none_init(void)
  840. {
  841. return 1;
  842. }
  843. void Curl_none_cleanup(void)
  844. { }
  845. int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM,
  846. int sockindex UNUSED_PARAM)
  847. {
  848. (void)conn;
  849. (void)sockindex;
  850. return 0;
  851. }
  852. int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM)
  853. {
  854. (void)conn;
  855. return -1;
  856. }
  857. CURLcode Curl_none_random(struct Curl_easy *data UNUSED_PARAM,
  858. unsigned char *entropy UNUSED_PARAM,
  859. size_t length UNUSED_PARAM)
  860. {
  861. (void)data;
  862. (void)entropy;
  863. (void)length;
  864. return CURLE_NOT_BUILT_IN;
  865. }
  866. void Curl_none_close_all(struct Curl_easy *data UNUSED_PARAM)
  867. {
  868. (void)data;
  869. }
  870. void Curl_none_session_free(void *ptr UNUSED_PARAM)
  871. {
  872. (void)ptr;
  873. }
  874. bool Curl_none_data_pending(const struct connectdata *conn UNUSED_PARAM,
  875. int connindex UNUSED_PARAM)
  876. {
  877. (void)conn;
  878. (void)connindex;
  879. return 0;
  880. }
  881. bool Curl_none_cert_status_request(void)
  882. {
  883. return FALSE;
  884. }
  885. CURLcode Curl_none_set_engine(struct Curl_easy *data UNUSED_PARAM,
  886. const char *engine UNUSED_PARAM)
  887. {
  888. (void)data;
  889. (void)engine;
  890. return CURLE_NOT_BUILT_IN;
  891. }
  892. CURLcode Curl_none_set_engine_default(struct Curl_easy *data UNUSED_PARAM)
  893. {
  894. (void)data;
  895. return CURLE_NOT_BUILT_IN;
  896. }
  897. struct curl_slist *Curl_none_engines_list(struct Curl_easy *data UNUSED_PARAM)
  898. {
  899. (void)data;
  900. return (struct curl_slist *)NULL;
  901. }
  902. bool Curl_none_false_start(void)
  903. {
  904. return FALSE;
  905. }
  906. #ifndef CURL_DISABLE_CRYPTO_AUTH
  907. CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
  908. unsigned char *md5sum, size_t md5len UNUSED_PARAM)
  909. {
  910. MD5_context *MD5pw;
  911. (void)md5len;
  912. MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
  913. if(!MD5pw)
  914. return CURLE_OUT_OF_MEMORY;
  915. Curl_MD5_update(MD5pw, input, curlx_uztoui(inputlen));
  916. Curl_MD5_final(MD5pw, md5sum);
  917. return CURLE_OK;
  918. }
  919. #else
  920. CURLcode Curl_none_md5sum(unsigned char *input UNUSED_PARAM,
  921. size_t inputlen UNUSED_PARAM,
  922. unsigned char *md5sum UNUSED_PARAM,
  923. size_t md5len UNUSED_PARAM)
  924. {
  925. (void)input;
  926. (void)inputlen;
  927. (void)md5sum;
  928. (void)md5len;
  929. return CURLE_NOT_BUILT_IN;
  930. }
  931. #endif
  932. static int Curl_multissl_init(void)
  933. {
  934. if(multissl_init(NULL))
  935. return 1;
  936. return Curl_ssl->init();
  937. }
  938. static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex)
  939. {
  940. if(multissl_init(NULL))
  941. return CURLE_FAILED_INIT;
  942. return Curl_ssl->connect_blocking(conn, sockindex);
  943. }
  944. static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn,
  945. int sockindex, bool *done)
  946. {
  947. if(multissl_init(NULL))
  948. return CURLE_FAILED_INIT;
  949. return Curl_ssl->connect_nonblocking(conn, sockindex, done);
  950. }
  951. static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl,
  952. CURLINFO info)
  953. {
  954. if(multissl_init(NULL))
  955. return NULL;
  956. return Curl_ssl->get_internals(connssl, info);
  957. }
  958. static void Curl_multissl_close(struct connectdata *conn, int sockindex)
  959. {
  960. if(multissl_init(NULL))
  961. return;
  962. Curl_ssl->close_one(conn, sockindex);
  963. }
  964. static const struct Curl_ssl Curl_ssl_multi = {
  965. { CURLSSLBACKEND_NONE, "multi" }, /* info */
  966. 0, /* supports nothing */
  967. (size_t)-1, /* something insanely large to be on the safe side */
  968. Curl_multissl_init, /* init */
  969. Curl_none_cleanup, /* cleanup */
  970. Curl_multissl_version, /* version */
  971. Curl_none_check_cxn, /* check_cxn */
  972. Curl_none_shutdown, /* shutdown */
  973. Curl_none_data_pending, /* data_pending */
  974. Curl_none_random, /* random */
  975. Curl_none_cert_status_request, /* cert_status_request */
  976. Curl_multissl_connect, /* connect */
  977. Curl_multissl_connect_nonblocking, /* connect_nonblocking */
  978. Curl_multissl_get_internals, /* get_internals */
  979. Curl_multissl_close, /* close_one */
  980. Curl_none_close_all, /* close_all */
  981. Curl_none_session_free, /* session_free */
  982. Curl_none_set_engine, /* set_engine */
  983. Curl_none_set_engine_default, /* set_engine_default */
  984. Curl_none_engines_list, /* engines_list */
  985. Curl_none_false_start, /* false_start */
  986. Curl_none_md5sum, /* md5sum */
  987. NULL /* sha256sum */
  988. };
  989. const struct Curl_ssl *Curl_ssl =
  990. #if defined(CURL_WITH_MULTI_SSL)
  991. &Curl_ssl_multi;
  992. #elif defined(USE_WOLFSSL)
  993. &Curl_ssl_wolfssl;
  994. #elif defined(USE_SECTRANSP)
  995. &Curl_ssl_sectransp;
  996. #elif defined(USE_GNUTLS)
  997. &Curl_ssl_gnutls;
  998. #elif defined(USE_GSKIT)
  999. &Curl_ssl_gskit;
  1000. #elif defined(USE_MBEDTLS)
  1001. &Curl_ssl_mbedtls;
  1002. #elif defined(USE_NSS)
  1003. &Curl_ssl_nss;
  1004. #elif defined(USE_OPENSSL)
  1005. &Curl_ssl_openssl;
  1006. #elif defined(USE_POLARSSL)
  1007. &Curl_ssl_polarssl;
  1008. #elif defined(USE_SCHANNEL)
  1009. &Curl_ssl_schannel;
  1010. #elif defined(USE_MESALINK)
  1011. &Curl_ssl_mesalink;
  1012. #elif defined(USE_BEARSSL)
  1013. &Curl_ssl_bearssl;
  1014. #else
  1015. #error "Missing struct Curl_ssl for selected SSL backend"
  1016. #endif
  1017. static const struct Curl_ssl *available_backends[] = {
  1018. #if defined(USE_WOLFSSL)
  1019. &Curl_ssl_wolfssl,
  1020. #endif
  1021. #if defined(USE_SECTRANSP)
  1022. &Curl_ssl_sectransp,
  1023. #endif
  1024. #if defined(USE_GNUTLS)
  1025. &Curl_ssl_gnutls,
  1026. #endif
  1027. #if defined(USE_GSKIT)
  1028. &Curl_ssl_gskit,
  1029. #endif
  1030. #if defined(USE_MBEDTLS)
  1031. &Curl_ssl_mbedtls,
  1032. #endif
  1033. #if defined(USE_NSS)
  1034. &Curl_ssl_nss,
  1035. #endif
  1036. #if defined(USE_OPENSSL)
  1037. &Curl_ssl_openssl,
  1038. #endif
  1039. #if defined(USE_POLARSSL)
  1040. &Curl_ssl_polarssl,
  1041. #endif
  1042. #if defined(USE_SCHANNEL)
  1043. &Curl_ssl_schannel,
  1044. #endif
  1045. #if defined(USE_MESALINK)
  1046. &Curl_ssl_mesalink,
  1047. #endif
  1048. NULL
  1049. };
  1050. static size_t Curl_multissl_version(char *buffer, size_t size)
  1051. {
  1052. static const struct Curl_ssl *selected;
  1053. static char backends[200];
  1054. static size_t total;
  1055. const struct Curl_ssl *current;
  1056. current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl;
  1057. if(current != selected) {
  1058. char *p = backends;
  1059. char *end = backends + sizeof(backends);
  1060. int i;
  1061. selected = current;
  1062. for(i = 0; available_backends[i] && p < (end - 4); i++) {
  1063. if(i)
  1064. *(p++) = ' ';
  1065. if(selected != available_backends[i])
  1066. *(p++) = '(';
  1067. p += available_backends[i]->version(p, end - p - 2);
  1068. if(selected != available_backends[i])
  1069. *(p++) = ')';
  1070. }
  1071. *p = '\0';
  1072. total = p - backends;
  1073. }
  1074. if(size > total)
  1075. memcpy(buffer, backends, total + 1);
  1076. else {
  1077. memcpy(buffer, backends, size - 1);
  1078. buffer[size - 1] = '\0';
  1079. }
  1080. return CURLMIN(size - 1, total);
  1081. }
  1082. static int multissl_init(const struct Curl_ssl *backend)
  1083. {
  1084. const char *env;
  1085. char *env_tmp;
  1086. if(Curl_ssl != &Curl_ssl_multi)
  1087. return 1;
  1088. if(backend) {
  1089. Curl_ssl = backend;
  1090. return 0;
  1091. }
  1092. if(!available_backends[0])
  1093. return 1;
  1094. env = env_tmp = curl_getenv("CURL_SSL_BACKEND");
  1095. #ifdef CURL_DEFAULT_SSL_BACKEND
  1096. if(!env)
  1097. env = CURL_DEFAULT_SSL_BACKEND;
  1098. #endif
  1099. if(env) {
  1100. int i;
  1101. for(i = 0; available_backends[i]; i++) {
  1102. if(strcasecompare(env, available_backends[i]->info.name)) {
  1103. Curl_ssl = available_backends[i];
  1104. curl_free(env_tmp);
  1105. return 0;
  1106. }
  1107. }
  1108. }
  1109. /* Fall back to first available backend */
  1110. Curl_ssl = available_backends[0];
  1111. curl_free(env_tmp);
  1112. return 0;
  1113. }
  1114. CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
  1115. const curl_ssl_backend ***avail)
  1116. {
  1117. int i;
  1118. if(avail)
  1119. *avail = (const curl_ssl_backend **)&available_backends;
  1120. if(Curl_ssl != &Curl_ssl_multi)
  1121. return id == Curl_ssl->info.id ||
  1122. (name && strcasecompare(name, Curl_ssl->info.name)) ?
  1123. CURLSSLSET_OK :
  1124. #if defined(CURL_WITH_MULTI_SSL)
  1125. CURLSSLSET_TOO_LATE;
  1126. #else
  1127. CURLSSLSET_UNKNOWN_BACKEND;
  1128. #endif
  1129. for(i = 0; available_backends[i]; i++) {
  1130. if(available_backends[i]->info.id == id ||
  1131. (name && strcasecompare(available_backends[i]->info.name, name))) {
  1132. multissl_init(available_backends[i]);
  1133. return CURLSSLSET_OK;
  1134. }
  1135. }
  1136. return CURLSSLSET_UNKNOWN_BACKEND;
  1137. }
  1138. #else /* USE_SSL */
  1139. CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
  1140. const curl_ssl_backend ***avail)
  1141. {
  1142. (void)id;
  1143. (void)name;
  1144. (void)avail;
  1145. return CURLSSLSET_NO_BACKENDS;
  1146. }
  1147. #endif /* !USE_SSL */