cyassl.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2011, 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 http://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. /*
  23. * Source file for all CyaSSL-specific code for the TLS/SSL layer. No code
  24. * but sslgen.c should ever call or use these functions.
  25. *
  26. */
  27. #include "setup.h"
  28. #ifdef USE_CYASSL
  29. #ifdef HAVE_LIMITS_H
  30. #include <limits.h>
  31. #endif
  32. #ifdef HAVE_SYS_SOCKET_H
  33. #include <sys/socket.h>
  34. #endif
  35. #include "urldata.h"
  36. #include "sendf.h"
  37. #include "inet_pton.h"
  38. #include "cyassl.h"
  39. #include "sslgen.h"
  40. #include "parsedate.h"
  41. #include "connect.h" /* for the connect timeout */
  42. #include "select.h"
  43. #include "rawstr.h"
  44. #define _MPRINTF_REPLACE /* use our functions only */
  45. #include <curl/mprintf.h>
  46. #include "curl_memory.h"
  47. /* The last #include file should be: */
  48. #include "memdebug.h"
  49. static Curl_recv cyassl_recv;
  50. static Curl_send cyassl_send;
  51. static int do_file_type(const char *type)
  52. {
  53. if(!type || !type[0])
  54. return SSL_FILETYPE_PEM;
  55. if(Curl_raw_equal(type, "PEM"))
  56. return SSL_FILETYPE_PEM;
  57. if(Curl_raw_equal(type, "DER"))
  58. return SSL_FILETYPE_ASN1;
  59. return -1;
  60. }
  61. /*
  62. * This function loads all the client/CA certificates and CRLs. Setup the TLS
  63. * layer and do all necessary magic.
  64. */
  65. static CURLcode
  66. cyassl_connect_step1(struct connectdata *conn,
  67. int sockindex)
  68. {
  69. struct SessionHandle *data = conn->data;
  70. struct ssl_connect_data* conssl = &conn->ssl[sockindex];
  71. SSL_METHOD* req_method = NULL;
  72. void* ssl_sessionid = NULL;
  73. curl_socket_t sockfd = conn->sock[sockindex];
  74. if(conssl->state == ssl_connection_complete)
  75. return CURLE_OK;
  76. /* CyaSSL doesn't support SSLv2 */
  77. if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
  78. failf(data, "CyaSSL does not support SSLv2");
  79. return CURLE_SSL_CONNECT_ERROR;
  80. }
  81. /* check to see if we've been told to use an explicit SSL/TLS version */
  82. switch(data->set.ssl.version) {
  83. case CURL_SSLVERSION_DEFAULT:
  84. /* we try to figure out version */
  85. req_method = SSLv23_client_method();
  86. break;
  87. case CURL_SSLVERSION_TLSv1:
  88. req_method = TLSv1_client_method();
  89. break;
  90. case CURL_SSLVERSION_SSLv3:
  91. req_method = SSLv3_client_method();
  92. break;
  93. default:
  94. req_method = TLSv1_client_method();
  95. }
  96. if(!req_method) {
  97. failf(data, "SSL: couldn't create a method!");
  98. return CURLE_OUT_OF_MEMORY;
  99. }
  100. if(conssl->ctx)
  101. SSL_CTX_free(conssl->ctx);
  102. conssl->ctx = SSL_CTX_new(req_method);
  103. if(!conssl->ctx) {
  104. failf(data, "SSL: couldn't create a context!");
  105. return CURLE_OUT_OF_MEMORY;
  106. }
  107. #ifndef NO_FILESYSTEM
  108. /* load trusted cacert */
  109. if(data->set.str[STRING_SSL_CAFILE]) {
  110. if(!SSL_CTX_load_verify_locations(conssl->ctx,
  111. data->set.str[STRING_SSL_CAFILE],
  112. data->set.str[STRING_SSL_CAPATH])) {
  113. if(data->set.ssl.verifypeer) {
  114. /* Fail if we insiste on successfully verifying the server. */
  115. failf(data,"error setting certificate verify locations:\n"
  116. " CAfile: %s\n CApath: %s\n",
  117. data->set.str[STRING_SSL_CAFILE]?
  118. data->set.str[STRING_SSL_CAFILE]: "none",
  119. data->set.str[STRING_SSL_CAPATH]?
  120. data->set.str[STRING_SSL_CAPATH] : "none");
  121. return CURLE_SSL_CACERT_BADFILE;
  122. }
  123. else {
  124. /* Just continue with a warning if no strict certificate
  125. verification is required. */
  126. infof(data, "error setting certificate verify locations,"
  127. " continuing anyway:\n");
  128. }
  129. }
  130. else {
  131. /* Everything is fine. */
  132. infof(data, "successfully set certificate verify locations:\n");
  133. }
  134. infof(data,
  135. " CAfile: %s\n"
  136. " CApath: %s\n",
  137. data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
  138. "none",
  139. data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
  140. "none");
  141. }
  142. /* Load the client certificate, and private key */
  143. if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) {
  144. int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]);
  145. if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT],
  146. file_type) != 1) {
  147. failf(data, "unable to use client certificate (no key or wrong pass"
  148. " phrase?)");
  149. return CURLE_SSL_CONNECT_ERROR;
  150. }
  151. file_type = do_file_type(data->set.str[STRING_KEY_TYPE]);
  152. if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY],
  153. file_type) != 1) {
  154. failf(data, "unable to set private key");
  155. return CURLE_SSL_CONNECT_ERROR;
  156. }
  157. }
  158. #else
  159. if(CyaSSL_no_filesystem_verify(conssl->ctx)!= SSL_SUCCESS) {
  160. return CURLE_SSL_CONNECT_ERROR;
  161. }
  162. #endif /* NO_FILESYSTEM */
  163. /* SSL always tries to verify the peer, this only says whether it should
  164. * fail to connect if the verification fails, or if it should continue
  165. * anyway. In the latter case the result of the verification is checked with
  166. * SSL_get_verify_result() below. */
  167. SSL_CTX_set_verify(conssl->ctx,
  168. data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
  169. NULL);
  170. /* Let's make an SSL structure */
  171. if(conssl->handle)
  172. SSL_free(conssl->handle);
  173. conssl->handle = SSL_new(conssl->ctx);
  174. if(!conssl->handle) {
  175. failf(data, "SSL: couldn't create a context (handle)!");
  176. return CURLE_OUT_OF_MEMORY;
  177. }
  178. /* Check if there's a cached ID we can/should use here! */
  179. if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
  180. /* we got a session id, use it! */
  181. if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
  182. failf(data, "SSL: SSL_set_session failed: %s",
  183. ERR_error_string(SSL_get_error(conssl->handle, 0),NULL));
  184. return CURLE_SSL_CONNECT_ERROR;
  185. }
  186. /* Informational message */
  187. infof (data, "SSL re-using session ID\n");
  188. }
  189. /* pass the raw socket into the SSL layer */
  190. if(!SSL_set_fd(conssl->handle, (int)sockfd)) {
  191. failf(data, "SSL: SSL_set_fd failed");
  192. return CURLE_SSL_CONNECT_ERROR;
  193. }
  194. conssl->connecting_state = ssl_connect_2;
  195. return CURLE_OK;
  196. }
  197. static CURLcode
  198. cyassl_connect_step2(struct connectdata *conn,
  199. int sockindex)
  200. {
  201. int ret = -1;
  202. struct SessionHandle *data = conn->data;
  203. struct ssl_connect_data* conssl = &conn->ssl[sockindex];
  204. infof(data, "CyaSSL: Connecting to %s:%d\n",
  205. conn->host.name, conn->remote_port);
  206. conn->recv[sockindex] = cyassl_recv;
  207. conn->send[sockindex] = cyassl_send;
  208. ret = SSL_connect(conssl->handle);
  209. if(ret != 1) {
  210. char error_buffer[80];
  211. int detail = SSL_get_error(conssl->handle, ret);
  212. if(SSL_ERROR_WANT_READ == detail) {
  213. conssl->connecting_state = ssl_connect_2_reading;
  214. return CURLE_OK;
  215. }
  216. if(SSL_ERROR_WANT_WRITE == detail) {
  217. conssl->connecting_state = ssl_connect_2_writing;
  218. return CURLE_OK;
  219. }
  220. failf(data, "SSL_connect failed with error %d: %s", detail,
  221. ERR_error_string(detail, error_buffer));
  222. return CURLE_SSL_CONNECT_ERROR;
  223. }
  224. conssl->connecting_state = ssl_connect_3;
  225. infof(data, "SSL connected");
  226. return CURLE_OK;
  227. }
  228. static CURLcode
  229. cyassl_connect_step3(struct connectdata *conn,
  230. int sockindex)
  231. {
  232. CURLcode retcode = CURLE_OK;
  233. void *old_ssl_sessionid=NULL;
  234. struct SessionHandle *data = conn->data;
  235. struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  236. int incache;
  237. SSL_SESSION *our_ssl_sessionid;
  238. DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
  239. our_ssl_sessionid = SSL_get_session(connssl->handle);
  240. incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
  241. if(incache) {
  242. if(old_ssl_sessionid != our_ssl_sessionid) {
  243. infof(data, "old SSL session ID is stale, removing\n");
  244. Curl_ssl_delsessionid(conn, old_ssl_sessionid);
  245. incache = FALSE;
  246. }
  247. }
  248. if(!incache) {
  249. retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
  250. 0 /* unknown size */);
  251. if(retcode) {
  252. failf(data, "failed to store ssl session");
  253. return retcode;
  254. }
  255. }
  256. connssl->connecting_state = ssl_connect_done;
  257. return retcode;
  258. }
  259. static ssize_t cyassl_send(struct connectdata *conn,
  260. int sockindex,
  261. const void *mem,
  262. size_t len,
  263. CURLcode *curlcode)
  264. {
  265. char error_buffer[80];
  266. int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
  267. int rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
  268. if(rc < 0) {
  269. int err = SSL_get_error(conn->ssl[sockindex].handle, rc);
  270. switch(err) {
  271. case SSL_ERROR_WANT_READ:
  272. case SSL_ERROR_WANT_WRITE:
  273. /* there's data pending, re-invoke SSL_write() */
  274. *curlcode = CURLE_AGAIN;
  275. return -1;
  276. default:
  277. failf(conn->data, "SSL write: %s, errno %d",
  278. ERR_error_string(err, error_buffer),
  279. SOCKERRNO);
  280. *curlcode = CURLE_SEND_ERROR;
  281. return -1;
  282. }
  283. }
  284. return rc;
  285. }
  286. void Curl_cyassl_close_all(struct SessionHandle *data)
  287. {
  288. (void)data;
  289. }
  290. void Curl_cyassl_close(struct connectdata *conn, int sockindex)
  291. {
  292. struct ssl_connect_data *conssl = &conn->ssl[sockindex];
  293. if(conssl->handle) {
  294. (void)SSL_shutdown(conssl->handle);
  295. SSL_free (conssl->handle);
  296. conssl->handle = NULL;
  297. }
  298. if(conssl->ctx) {
  299. SSL_CTX_free (conssl->ctx);
  300. conssl->ctx = NULL;
  301. }
  302. }
  303. static ssize_t cyassl_recv(struct connectdata *conn,
  304. int num,
  305. char *buf,
  306. size_t buffersize,
  307. CURLcode *curlcode)
  308. {
  309. char error_buffer[80];
  310. int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
  311. int nread = SSL_read(conn->ssl[num].handle, buf, buffsize);
  312. if(nread < 0) {
  313. int err = SSL_get_error(conn->ssl[num].handle, nread);
  314. switch(err) {
  315. case SSL_ERROR_ZERO_RETURN: /* no more data */
  316. break;
  317. case SSL_ERROR_WANT_READ:
  318. case SSL_ERROR_WANT_WRITE:
  319. /* there's data pending, re-invoke SSL_read() */
  320. *curlcode = CURLE_AGAIN;
  321. return -1;
  322. default:
  323. failf(conn->data, "SSL read: %s, errno %d",
  324. ERR_error_string(err, error_buffer),
  325. SOCKERRNO);
  326. *curlcode = CURLE_RECV_ERROR;
  327. return -1;
  328. }
  329. }
  330. return nread;
  331. }
  332. void Curl_cyassl_session_free(void *ptr)
  333. {
  334. (void)ptr;
  335. /* CyaSSL reuses sessions on own, no free */
  336. }
  337. size_t Curl_cyassl_version(char *buffer, size_t size)
  338. {
  339. #ifdef CYASSL_VERSION
  340. return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
  341. #else
  342. return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8");
  343. #endif
  344. }
  345. int Curl_cyassl_init(void)
  346. {
  347. InitCyaSSL();
  348. return 1;
  349. }
  350. bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex)
  351. {
  352. if(conn->ssl[connindex].handle) /* SSL is in use */
  353. return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
  354. else
  355. return FALSE;
  356. }
  357. /*
  358. * This function is called to shut down the SSL layer but keep the
  359. * socket open (CCC - Clear Command Channel)
  360. */
  361. int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
  362. {
  363. int retval = 0;
  364. struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  365. if(connssl->handle) {
  366. SSL_free (connssl->handle);
  367. connssl->handle = NULL;
  368. }
  369. return retval;
  370. }
  371. static CURLcode
  372. cyassl_connect_common(struct connectdata *conn,
  373. int sockindex,
  374. bool nonblocking,
  375. bool *done)
  376. {
  377. CURLcode retcode;
  378. struct SessionHandle *data = conn->data;
  379. struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  380. curl_socket_t sockfd = conn->sock[sockindex];
  381. long timeout_ms;
  382. int what;
  383. /* check if the connection has already been established */
  384. if(ssl_connection_complete == connssl->state) {
  385. *done = TRUE;
  386. return CURLE_OK;
  387. }
  388. if(ssl_connect_1==connssl->connecting_state) {
  389. /* Find out how much more time we're allowed */
  390. timeout_ms = Curl_timeleft(data, NULL, TRUE);
  391. if(timeout_ms < 0) {
  392. /* no need to continue if time already is up */
  393. failf(data, "SSL connection timeout");
  394. return CURLE_OPERATION_TIMEDOUT;
  395. }
  396. retcode = cyassl_connect_step1(conn, sockindex);
  397. if(retcode)
  398. return retcode;
  399. }
  400. while(ssl_connect_2 == connssl->connecting_state ||
  401. ssl_connect_2_reading == connssl->connecting_state ||
  402. ssl_connect_2_writing == connssl->connecting_state) {
  403. /* check allowed time left */
  404. timeout_ms = Curl_timeleft(data, NULL, TRUE);
  405. if(timeout_ms < 0) {
  406. /* no need to continue if time already is up */
  407. failf(data, "SSL connection timeout");
  408. return CURLE_OPERATION_TIMEDOUT;
  409. }
  410. /* if ssl is expecting something, check if it's available. */
  411. if(connssl->connecting_state == ssl_connect_2_reading
  412. || connssl->connecting_state == ssl_connect_2_writing) {
  413. curl_socket_t writefd = ssl_connect_2_writing==
  414. connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
  415. curl_socket_t readfd = ssl_connect_2_reading==
  416. connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
  417. what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
  418. if(what < 0) {
  419. /* fatal error */
  420. failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
  421. return CURLE_SSL_CONNECT_ERROR;
  422. }
  423. else if(0 == what) {
  424. if(nonblocking) {
  425. *done = FALSE;
  426. return CURLE_OK;
  427. }
  428. else {
  429. /* timeout */
  430. failf(data, "SSL connection timeout");
  431. return CURLE_OPERATION_TIMEDOUT;
  432. }
  433. }
  434. /* socket is readable or writable */
  435. }
  436. /* Run transaction, and return to the caller if it failed or if
  437. * this connection is part of a multi handle and this loop would
  438. * execute again. This permits the owner of a multi handle to
  439. * abort a connection attempt before step2 has completed while
  440. * ensuring that a client using select() or epoll() will always
  441. * have a valid fdset to wait on.
  442. */
  443. retcode = cyassl_connect_step2(conn, sockindex);
  444. if(retcode || (nonblocking &&
  445. (ssl_connect_2 == connssl->connecting_state ||
  446. ssl_connect_2_reading == connssl->connecting_state ||
  447. ssl_connect_2_writing == connssl->connecting_state)))
  448. return retcode;
  449. } /* repeat step2 until all transactions are done. */
  450. if(ssl_connect_3==connssl->connecting_state) {
  451. retcode = cyassl_connect_step3(conn, sockindex);
  452. if(retcode)
  453. return retcode;
  454. }
  455. if(ssl_connect_done==connssl->connecting_state) {
  456. connssl->state = ssl_connection_complete;
  457. conn->recv[sockindex] = cyassl_recv;
  458. conn->send[sockindex] = cyassl_send;
  459. *done = TRUE;
  460. }
  461. else
  462. *done = FALSE;
  463. /* Reset our connect state machine */
  464. connssl->connecting_state = ssl_connect_1;
  465. return CURLE_OK;
  466. }
  467. CURLcode
  468. Curl_cyassl_connect_nonblocking(struct connectdata *conn,
  469. int sockindex,
  470. bool *done)
  471. {
  472. return cyassl_connect_common(conn, sockindex, TRUE, done);
  473. }
  474. CURLcode
  475. Curl_cyassl_connect(struct connectdata *conn,
  476. int sockindex)
  477. {
  478. CURLcode retcode;
  479. bool done = FALSE;
  480. retcode = cyassl_connect_common(conn, sockindex, FALSE, &done);
  481. if(retcode)
  482. return retcode;
  483. DEBUGASSERT(done);
  484. return CURLE_OK;
  485. }
  486. #endif