2
0

axtls.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 2010, DirecTV
  9. * contact: Eric Hu <ehu@directv.com>
  10. *
  11. * This software is licensed as described in the file COPYING, which
  12. * you should have received as part of this distribution. The terms
  13. * are also available at http://curl.haxx.se/docs/copyright.html.
  14. *
  15. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  16. * copies of the Software, and permit persons to whom the Software is
  17. * furnished to do so, under the terms of the COPYING file.
  18. *
  19. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  20. * KIND, either express or implied.
  21. *
  22. ***************************************************************************/
  23. /*
  24. * Source file for all axTLS-specific code for the TLS/SSL layer. No code
  25. * but sslgen.c should ever call or use these functions.
  26. */
  27. #include "setup.h"
  28. #ifdef USE_AXTLS
  29. #include <axTLS/ssl.h>
  30. #include "axtls.h"
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <ctype.h>
  34. #ifdef HAVE_SYS_SOCKET_H
  35. #include <sys/socket.h>
  36. #endif
  37. #include "sendf.h"
  38. #include "inet_pton.h"
  39. #include "sslgen.h"
  40. #include "parsedate.h"
  41. #include "connect.h" /* for the connect timeout */
  42. #include "select.h"
  43. #define _MPRINTF_REPLACE /* use our functions only */
  44. #include <curl/mprintf.h>
  45. #include "memory.h"
  46. /* The last #include file should be: */
  47. #include "memdebug.h"
  48. /* SSL_read is opied from axTLS compat layer */
  49. static int SSL_read(SSL *ssl, void *buf, int num)
  50. {
  51. uint8_t *read_buf;
  52. int ret;
  53. while((ret = ssl_read(ssl, &read_buf)) == SSL_OK);
  54. if(ret > SSL_OK){
  55. memcpy(buf, read_buf, ret > num ? num : ret);
  56. }
  57. return ret;
  58. }
  59. /* Global axTLS init, called from Curl_ssl_init() */
  60. int Curl_axtls_init(void)
  61. {
  62. /* axTLS has no global init. Everything is done through SSL and SSL_CTX
  63. * structs stored in connectdata structure. Perhaps can move to axtls.h.
  64. */
  65. return 1;
  66. }
  67. int Curl_axtls_cleanup(void)
  68. {
  69. /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */
  70. return 1;
  71. }
  72. static CURLcode map_error_to_curl(int axtls_err)
  73. {
  74. switch (axtls_err)
  75. {
  76. case SSL_ERROR_NOT_SUPPORTED:
  77. case SSL_ERROR_INVALID_VERSION:
  78. case -70: /* protocol version alert from server */
  79. return CURLE_UNSUPPORTED_PROTOCOL;
  80. break;
  81. case SSL_ERROR_NO_CIPHER:
  82. return CURLE_SSL_CIPHER;
  83. break;
  84. case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
  85. case SSL_ERROR_NO_CERT_DEFINED:
  86. case -42: /* bad certificate alert from server */
  87. case -43: /* unsupported cert alert from server */
  88. case -44: /* cert revoked alert from server */
  89. case -45: /* cert expired alert from server */
  90. case -46: /* cert unknown alert from server */
  91. return CURLE_SSL_CERTPROBLEM;
  92. break;
  93. case SSL_X509_ERROR(X509_NOT_OK):
  94. case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
  95. case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
  96. case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
  97. case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
  98. case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
  99. case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
  100. case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
  101. case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
  102. return CURLE_PEER_FAILED_VERIFICATION;
  103. break;
  104. case -48: /* unknown ca alert from server */
  105. return CURLE_SSL_CACERT;
  106. break;
  107. case -49: /* access denied alert from server */
  108. return CURLE_REMOTE_ACCESS_DENIED;
  109. break;
  110. case SSL_ERROR_CONN_LOST:
  111. case SSL_ERROR_SOCK_SETUP_FAILURE:
  112. case SSL_ERROR_INVALID_HANDSHAKE:
  113. case SSL_ERROR_INVALID_PROT_MSG:
  114. case SSL_ERROR_INVALID_HMAC:
  115. case SSL_ERROR_INVALID_SESSION:
  116. case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */
  117. case SSL_ERROR_FINISHED_INVALID:
  118. case SSL_ERROR_NO_CLIENT_RENOG:
  119. default:
  120. return CURLE_SSL_CONNECT_ERROR;
  121. break;
  122. }
  123. }
  124. static Curl_recv axtls_recv;
  125. static Curl_send axtls_send;
  126. /*
  127. * This function is called after the TCP connect has completed. Setup the TLS
  128. * layer and do all necessary magic.
  129. */
  130. CURLcode
  131. Curl_axtls_connect(struct connectdata *conn,
  132. int sockindex)
  133. {
  134. struct SessionHandle *data = conn->data;
  135. SSL_CTX *ssl_ctx;
  136. SSL *ssl;
  137. int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
  138. int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
  139. int i, ssl_fcn_return;
  140. const uint8_t *ssl_sessionid;
  141. size_t ssl_idsize;
  142. const char *x509;
  143. /* Assuming users will not compile in custom key/cert to axTLS */
  144. uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER;
  145. if(conn->ssl[sockindex].state == ssl_connection_complete)
  146. /* to make us tolerant against being called more than once for the
  147. same connection */
  148. return CURLE_OK;
  149. /* axTLS only supports TLSv1 */
  150. /* check to see if we've been told to use an explicit SSL/TLS version */
  151. switch(data->set.ssl.version) {
  152. case CURL_SSLVERSION_DEFAULT:
  153. case CURL_SSLVERSION_TLSv1:
  154. break;
  155. default:
  156. failf(data, "axTLS only supports TLSv1");
  157. return CURLE_SSL_CONNECT_ERROR;
  158. }
  159. #ifdef AXTLSDEBUG
  160. client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
  161. #endif /* AXTLSDEBUG */
  162. /* Allocate an SSL_CTX struct */
  163. ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
  164. if(ssl_ctx == NULL) {
  165. failf(data, "unable to create client SSL context");
  166. return CURLE_SSL_CONNECT_ERROR;
  167. }
  168. /* Load the trusted CA cert bundle file */
  169. if(data->set.ssl.CAfile) {
  170. if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
  171. != SSL_OK){
  172. infof(data, "error reading ca cert file %s \n",
  173. data->set.ssl.CAfile);
  174. if(data->set.ssl.verifypeer){
  175. Curl_axtls_close(conn, sockindex);
  176. return CURLE_SSL_CACERT_BADFILE;
  177. }
  178. }
  179. else
  180. infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
  181. }
  182. /* gtls.c tasks we're skipping for now:
  183. * 1) certificate revocation list checking
  184. * 2) dns name assignment to host
  185. * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore
  186. * 4) set certificate priority. axTLS ignores type and sends certs in
  187. * order added. can probably ignore this.
  188. */
  189. /* Load client certificate */
  190. if(data->set.str[STRING_CERT]){
  191. i=0;
  192. /* Instead of trying to analyze cert type here, let axTLS try them all. */
  193. while(cert_types[i] != 0){
  194. ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
  195. data->set.str[STRING_CERT], NULL);
  196. if(ssl_fcn_return == SSL_OK){
  197. infof(data, "successfully read cert file %s \n",
  198. data->set.str[STRING_CERT]);
  199. break;
  200. }
  201. i++;
  202. }
  203. /* Tried all cert types, none worked. */
  204. if(cert_types[i] == 0){
  205. failf(data, "%s is not x509 or pkcs12 format",
  206. data->set.str[STRING_CERT]);
  207. Curl_axtls_close(conn, sockindex);
  208. return CURLE_SSL_CERTPROBLEM;
  209. }
  210. }
  211. /* Load client key.
  212. If a pkcs12 file successfully loaded a cert, then there's nothing to do
  213. because the key has already been loaded. */
  214. if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12){
  215. i=0;
  216. /* Instead of trying to analyze key type here, let axTLS try them all. */
  217. while(key_types[i] != 0){
  218. ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
  219. data->set.str[STRING_KEY], NULL);
  220. if(ssl_fcn_return == SSL_OK){
  221. infof(data, "successfully read key file %s \n",
  222. data->set.str[STRING_KEY]);
  223. break;
  224. }
  225. i++;
  226. }
  227. /* Tried all key types, none worked. */
  228. if(key_types[i] == 0){
  229. failf(data, "Failure: %s is not a supported key file",
  230. data->set.str[STRING_KEY]);
  231. Curl_axtls_close(conn, sockindex);
  232. return CURLE_SSL_CONNECT_ERROR;
  233. }
  234. }
  235. /* gtls.c does more here that is being left out for now
  236. * 1) set session credentials. can probably ignore since axtls puts this
  237. * info in the ssl_ctx struct
  238. * 2) setting up callbacks. these seem gnutls specific
  239. */
  240. /* In axTLS, handshaking happens inside ssl_client_new. */
  241. if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
  242. /* we got a session id, use it! */
  243. infof (data, "SSL re-using session ID\n");
  244. ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
  245. ssl_sessionid, (uint8_t)ssl_idsize);
  246. }
  247. else
  248. ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
  249. /* Check to make sure handshake was ok. */
  250. ssl_fcn_return = ssl_handshake_status(ssl);
  251. if(ssl_fcn_return != SSL_OK){
  252. Curl_axtls_close(conn, sockindex);
  253. ssl_display_error(ssl_fcn_return); /* goes to stdout. */
  254. return map_error_to_curl(ssl_fcn_return);
  255. }
  256. infof (data, "handshake completed successfully\n");
  257. /* Here, gtls.c gets the peer certificates and fails out depending on
  258. * settings in "data." axTLS api doesn't have get cert chain fcn, so omit?
  259. */
  260. /* Verify server's certificate */
  261. if(data->set.ssl.verifypeer){
  262. if(ssl_verify_cert(ssl) != SSL_OK){
  263. Curl_axtls_close(conn, sockindex);
  264. failf(data, "server cert verify failed");
  265. return CURLE_SSL_CONNECT_ERROR;
  266. }
  267. }
  268. else
  269. infof(data, "\t server certificate verification SKIPPED\n");
  270. /* Here, gtls.c does issuer verfication. axTLS has no straightforward
  271. * equivalent, so omitting for now.*/
  272. /* See if common name was set in server certificate */
  273. x509 = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
  274. if(x509 == NULL)
  275. infof(data, "error fetching CN from cert\n");
  276. /* Here, gtls.c does the following
  277. * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but
  278. * it seems useful. Omitting for now.
  279. * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert
  280. * 3) displays a bunch of cert information. axTLS doesn't support most of
  281. * this, but a couple fields are available.
  282. */
  283. /* General housekeeping */
  284. conn->ssl[sockindex].state = ssl_connection_complete;
  285. conn->ssl[sockindex].ssl = ssl;
  286. conn->ssl[sockindex].ssl_ctx = ssl_ctx;
  287. conn->recv[sockindex] = axtls_recv;
  288. conn->send[sockindex] = axtls_send;
  289. /* Put our freshly minted SSL session in cache */
  290. ssl_idsize = ssl_get_session_id_size(ssl);
  291. ssl_sessionid = ssl_get_session_id(ssl);
  292. if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
  293. != CURLE_OK)
  294. infof (data, "failed to add session to cache\n");
  295. return CURLE_OK;
  296. }
  297. /* return number of sent (non-SSL) bytes */
  298. static ssize_t axtls_send(struct connectdata *conn,
  299. int sockindex,
  300. const void *mem,
  301. size_t len,
  302. CURLcode *err)
  303. {
  304. /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
  305. int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len);
  306. infof(conn->data, " axtls_send\n");
  307. if(rc < 0 ) {
  308. *err = map_error_to_curl(rc);
  309. rc = -1; /* generic error code for send failure */
  310. }
  311. *err = CURLE_OK;
  312. return rc;
  313. }
  314. void Curl_axtls_close_all(struct SessionHandle *data)
  315. {
  316. (void)data;
  317. infof(data, " Curl_axtls_close_all\n");
  318. }
  319. void Curl_axtls_close(struct connectdata *conn, int sockindex)
  320. {
  321. struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  322. infof(conn->data, " Curl_axtls_close\n");
  323. if(connssl->ssl) {
  324. /* line from ssluse.c: (void)SSL_shutdown(connssl->ssl);
  325. axTLS compat layer does nothing for SSL_shutdown */
  326. /* The following line is from ssluse.c. There seems to be no axTLS
  327. equivalent. ssl_free and ssl_ctx_free close things.
  328. SSL_set_connect_state(connssl->handle); */
  329. ssl_free (connssl->ssl);
  330. connssl->ssl = NULL;
  331. }
  332. if(connssl->ssl_ctx) {
  333. ssl_ctx_free (connssl->ssl_ctx);
  334. connssl->ssl_ctx = NULL;
  335. }
  336. }
  337. /*
  338. * This function is called to shut down the SSL layer but keep the
  339. * socket open (CCC - Clear Command Channel)
  340. */
  341. int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
  342. {
  343. /* Outline taken from ssluse.c since functions are in axTLS compat layer.
  344. axTLS's error set is much smaller, so a lot of error-handling was removed.
  345. */
  346. int retval = 0;
  347. struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  348. struct SessionHandle *data = conn->data;
  349. char buf[120]; /* We will use this for the OpenSSL error buffer, so it has
  350. to be at least 120 bytes long. */
  351. ssize_t nread;
  352. infof(conn->data, " Curl_axtls_shutdown\n");
  353. /* This has only been tested on the proftpd server, and the mod_tls code
  354. sends a close notify alert without waiting for a close notify alert in
  355. response. Thus we wait for a close notify alert from the server, but
  356. we do not send one. Let's hope other servers do the same... */
  357. /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
  358. if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
  359. (void)SSL_shutdown(connssl->ssl);
  360. */
  361. if(connssl->ssl) {
  362. int what = Curl_socket_ready(conn->sock[sockindex],
  363. CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
  364. if(what > 0) {
  365. /* Something to read, let's do it and hope that it is the close
  366. notify alert from the server */
  367. nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf,
  368. sizeof(buf));
  369. if (nread < SSL_OK){
  370. failf(data, "close notify alert not received during shutdown");
  371. retval = -1;
  372. }
  373. }
  374. else if(0 == what) {
  375. /* timeout */
  376. failf(data, "SSL shutdown timeout");
  377. }
  378. else {
  379. /* anything that gets here is fatally bad */
  380. failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
  381. retval = -1;
  382. }
  383. ssl_free (connssl->ssl);
  384. connssl->ssl = NULL;
  385. }
  386. return retval;
  387. }
  388. static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
  389. int num, /* socketindex */
  390. char *buf, /* store read data here */
  391. size_t buffersize, /* max amount to read */
  392. CURLcode *err)
  393. {
  394. struct ssl_connect_data *connssl = &conn->ssl[num];
  395. ssize_t ret = 0;
  396. infof(conn->data, " axtls_recv\n");
  397. if(connssl){
  398. ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize);
  399. /* axTLS isn't terribly generous about error reporting */
  400. /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS
  401. team approves proposed fix. */
  402. if(ret == -3 ){
  403. Curl_axtls_close(conn, num);
  404. }
  405. else if(ret < 0) {
  406. failf(conn->data, "axTLS recv error (%d)", (int)ret);
  407. *err = map_error_to_curl(ret);
  408. return -1;
  409. }
  410. }
  411. *err = CURLE_OK;
  412. return ret;
  413. }
  414. /*
  415. * Return codes:
  416. * 1 means the connection is still in place
  417. * 0 means the connection has been closed
  418. * -1 means the connection status is unknown
  419. */
  420. int Curl_axtls_check_cxn(struct connectdata *conn)
  421. {
  422. /* ssluse.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1);
  423. axTLS compat layer always returns the last argument, so connection is
  424. always alive? */
  425. infof(conn->data, " Curl_axtls_check_cxn\n");
  426. return 1; /* connection still in place */
  427. }
  428. void Curl_axtls_session_free(void *ptr)
  429. {
  430. (void)ptr;
  431. /* free the ID */
  432. /* both ssluse.c and gtls.c do something here, but axTLS's OpenSSL
  433. compatibility layer does nothing, so we do nothing too. */
  434. }
  435. size_t Curl_axtls_version(char *buffer, size_t size)
  436. {
  437. return snprintf(buffer, size, "axTLS/%s", ssl_version());
  438. }
  439. #endif /* USE_AXTLS */