qssl.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2013, 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. #include "curl_setup.h"
  23. #ifdef USE_QSOSSL
  24. #include <qsossl.h>
  25. #ifdef HAVE_LIMITS_H
  26. # include <limits.h>
  27. #endif
  28. #include <curl/curl.h>
  29. #include "urldata.h"
  30. #include "sendf.h"
  31. #include "qssl.h"
  32. #include "vtls.h"
  33. #include "connect.h" /* for the connect timeout */
  34. #include "select.h"
  35. #include "x509asn1.h"
  36. #include "curl_memory.h"
  37. /* The last #include file should be: */
  38. #include "memdebug.h"
  39. int Curl_qsossl_init(void)
  40. {
  41. /* Nothing to do here. We must have connection data to initialize ssl, so
  42. * defer.
  43. */
  44. return 1;
  45. }
  46. void Curl_qsossl_cleanup(void)
  47. {
  48. /* Nothing to do. */
  49. }
  50. static CURLcode Curl_qsossl_init_session(struct SessionHandle * data)
  51. {
  52. int rc;
  53. char * certname;
  54. SSLInit initstr;
  55. SSLInitApp initappstr;
  56. /* Initialize the job for SSL according to the current parameters.
  57. * QsoSSL offers two ways to do it: SSL_Init_Application() that uses an
  58. * application identifier to select certificates in the main certificate
  59. * store, and SSL_Init() that uses named keyring files and a password.
  60. * It is not possible to have different keyrings for the CAs and the
  61. * local certificate. We thus use the certificate name to identify the
  62. * keyring if given, else the CA file name.
  63. * If the key file name is given, it is taken as the password for the
  64. * keyring in certificate file.
  65. * We first try to SSL_Init_Application(), then SSL_Init() if it failed.
  66. */
  67. certname = data->set.str[STRING_CERT];
  68. if(!certname) {
  69. certname = data->set.str[STRING_SSL_CAFILE];
  70. if(!certname)
  71. return CURLE_OK; /* Use previous setup. */
  72. }
  73. memset((char *) &initappstr, 0, sizeof initappstr);
  74. initappstr.applicationID = certname;
  75. initappstr.applicationIDLen = strlen(certname);
  76. initappstr.protocol = SSL_VERSION_CURRENT; /* TLSV1 compat. SSLV[23]. */
  77. initappstr.sessionType = SSL_REGISTERED_AS_CLIENT;
  78. rc = SSL_Init_Application(&initappstr);
  79. if(rc == SSL_ERROR_NOT_REGISTERED) {
  80. initstr.keyringFileName = certname;
  81. initstr.keyringPassword = data->set.str[STRING_KEY];
  82. initstr.cipherSuiteList = NULL; /* Use default. */
  83. initstr.cipherSuiteListLen = 0;
  84. rc = SSL_Init(&initstr);
  85. }
  86. switch (rc) {
  87. case 0: /* No error. */
  88. break;
  89. case SSL_ERROR_IO:
  90. failf(data, "SSL_Init() I/O error: %s", strerror(errno));
  91. return CURLE_SSL_CONNECT_ERROR;
  92. case SSL_ERROR_BAD_CIPHER_SUITE:
  93. return CURLE_SSL_CIPHER;
  94. case SSL_ERROR_KEYPASSWORD_EXPIRED:
  95. case SSL_ERROR_NOT_REGISTERED:
  96. return CURLE_SSL_CONNECT_ERROR;
  97. case SSL_ERROR_NO_KEYRING:
  98. return CURLE_SSL_CACERT;
  99. case SSL_ERROR_CERT_EXPIRED:
  100. return CURLE_SSL_CERTPROBLEM;
  101. default:
  102. failf(data, "SSL_Init(): %s", SSL_Strerror(rc, NULL));
  103. return CURLE_SSL_CONNECT_ERROR;
  104. }
  105. return CURLE_OK;
  106. }
  107. static CURLcode Curl_qsossl_create(struct connectdata * conn, int sockindex)
  108. {
  109. SSLHandle * h;
  110. struct ssl_connect_data * connssl = &conn->ssl[sockindex];
  111. h = SSL_Create(conn->sock[sockindex], SSL_ENCRYPT);
  112. if(!h) {
  113. failf(conn->data, "SSL_Create() I/O error: %s", strerror(errno));
  114. return CURLE_SSL_CONNECT_ERROR;
  115. }
  116. connssl->handle = h;
  117. return CURLE_OK;
  118. }
  119. static int Curl_qsossl_trap_cert(SSLHandle * h)
  120. {
  121. return 1; /* Accept certificate. */
  122. }
  123. static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex)
  124. {
  125. int rc;
  126. struct SessionHandle * data = conn->data;
  127. struct ssl_connect_data * connssl = &conn->ssl[sockindex];
  128. SSLHandle * h = connssl->handle;
  129. long timeout_ms;
  130. h->exitPgm = data->set.ssl.verifypeer? NULL: Curl_qsossl_trap_cert;
  131. /* figure out how long time we should wait at maximum */
  132. timeout_ms = Curl_timeleft(data, NULL, TRUE);
  133. if(timeout_ms < 0) {
  134. /* time-out, bail out, go home */
  135. failf(data, "Connection time-out");
  136. return CURLE_OPERATION_TIMEDOUT;
  137. }
  138. /* SSL_Handshake() timeout resolution is second, so round up. */
  139. h->timeout = (timeout_ms + 1000 - 1) / 1000;
  140. /* Set-up protocol. */
  141. switch (data->set.ssl.version) {
  142. default:
  143. case CURL_SSLVERSION_DEFAULT:
  144. h->protocol = SSL_VERSION_CURRENT; /* TLSV1 compat. SSLV[23]. */
  145. break;
  146. case CURL_SSLVERSION_TLSv1:
  147. h->protocol = TLS_VERSION_1;
  148. break;
  149. case CURL_SSLVERSION_SSLv2:
  150. h->protocol = SSL_VERSION_2;
  151. break;
  152. case CURL_SSLVERSION_SSLv3:
  153. h->protocol = SSL_VERSION_3;
  154. break;
  155. case CURL_SSLVERSION_TLSv1_0:
  156. case CURL_SSLVERSION_TLSv1_1:
  157. case CURL_SSLVERSION_TLSv1_2:
  158. failf(data, "TLS minor version cannot be set");
  159. return CURLE_SSL_CONNECT_ERROR;
  160. }
  161. h->peerCert = NULL;
  162. h->peerCertLen = 0;
  163. rc = SSL_Handshake(h, SSL_HANDSHAKE_AS_CLIENT);
  164. switch (rc) {
  165. case 0: /* No error. */
  166. break;
  167. case SSL_ERROR_BAD_CERTIFICATE:
  168. case SSL_ERROR_BAD_CERT_SIG:
  169. case SSL_ERROR_NOT_TRUSTED_ROOT:
  170. return CURLE_PEER_FAILED_VERIFICATION;
  171. case SSL_ERROR_BAD_CIPHER_SUITE:
  172. case SSL_ERROR_NO_CIPHERS:
  173. return CURLE_SSL_CIPHER;
  174. case SSL_ERROR_CERTIFICATE_REJECTED:
  175. case SSL_ERROR_CERT_EXPIRED:
  176. case SSL_ERROR_NO_CERTIFICATE:
  177. return CURLE_SSL_CERTPROBLEM;
  178. case SSL_ERROR_IO:
  179. failf(data, "SSL_Handshake() I/O error: %s", strerror(errno));
  180. return CURLE_SSL_CONNECT_ERROR;
  181. default:
  182. failf(data, "SSL_Handshake(): %s", SSL_Strerror(rc, NULL));
  183. return CURLE_SSL_CONNECT_ERROR;
  184. }
  185. /* Verify host. */
  186. rc = Curl_verifyhost(conn, h->peerCert, h->peerCert + h->peerCertLen);
  187. if(rc != CURLE_OK)
  188. return rc;
  189. /* Gather certificate info. */
  190. if(data->set.ssl.certinfo) {
  191. if(Curl_ssl_init_certinfo(data, 1))
  192. return CURLE_OUT_OF_MEMORY;
  193. if(h->peerCert) {
  194. rc = Curl_extract_certinfo(conn, 0, h->peerCert,
  195. h->peerCert + h->peerCertLen);
  196. if(rc != CURLE_OK)
  197. return rc;
  198. }
  199. }
  200. return CURLE_OK;
  201. }
  202. static Curl_recv qsossl_recv;
  203. static Curl_send qsossl_send;
  204. CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex)
  205. {
  206. struct SessionHandle * data = conn->data;
  207. struct ssl_connect_data * connssl = &conn->ssl[sockindex];
  208. int rc;
  209. rc = Curl_qsossl_init_session(data);
  210. if(rc == CURLE_OK) {
  211. rc = Curl_qsossl_create(conn, sockindex);
  212. if(rc == CURLE_OK) {
  213. rc = Curl_qsossl_handshake(conn, sockindex);
  214. if(rc != CURLE_OK)
  215. SSL_Destroy(connssl->handle);
  216. }
  217. }
  218. if(rc == CURLE_OK) {
  219. conn->recv[sockindex] = qsossl_recv;
  220. conn->send[sockindex] = qsossl_send;
  221. connssl->state = ssl_connection_complete;
  222. }
  223. else {
  224. connssl->handle = NULL;
  225. connssl->use = FALSE;
  226. connssl->state = ssl_connection_none;
  227. }
  228. return rc;
  229. }
  230. static int Curl_qsossl_close_one(struct ssl_connect_data * conn,
  231. struct SessionHandle * data)
  232. {
  233. int rc;
  234. if(!conn->handle)
  235. return 0;
  236. rc = SSL_Destroy(conn->handle);
  237. if(rc) {
  238. if(rc == SSL_ERROR_IO) {
  239. failf(data, "SSL_Destroy() I/O error: %s", strerror(errno));
  240. return -1;
  241. }
  242. /* An SSL error. */
  243. failf(data, "SSL_Destroy() returned error %s", SSL_Strerror(rc, NULL));
  244. return -1;
  245. }
  246. conn->handle = NULL;
  247. return 0;
  248. }
  249. void Curl_qsossl_close(struct connectdata *conn, int sockindex)
  250. {
  251. struct SessionHandle *data = conn->data;
  252. struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  253. if(connssl->use)
  254. (void) Curl_qsossl_close_one(connssl, data);
  255. }
  256. int Curl_qsossl_close_all(struct SessionHandle * data)
  257. {
  258. /* Unimplemented. */
  259. (void) data;
  260. return 0;
  261. }
  262. int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex)
  263. {
  264. struct ssl_connect_data * connssl = &conn->ssl[sockindex];
  265. struct SessionHandle *data = conn->data;
  266. ssize_t nread;
  267. int what;
  268. int rc;
  269. char buf[120];
  270. if(!connssl->handle)
  271. return 0;
  272. if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
  273. return 0;
  274. if(Curl_qsossl_close_one(connssl, data))
  275. return -1;
  276. rc = 0;
  277. what = Curl_socket_ready(conn->sock[sockindex],
  278. CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
  279. for(;;) {
  280. if(what < 0) {
  281. /* anything that gets here is fatally bad */
  282. failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
  283. rc = -1;
  284. break;
  285. }
  286. if(!what) { /* timeout */
  287. failf(data, "SSL shutdown timeout");
  288. break;
  289. }
  290. /* Something to read, let's do it and hope that it is the close
  291. notify alert from the server. No way to SSL_Read now, so use read(). */
  292. nread = read(conn->sock[sockindex], buf, sizeof(buf));
  293. if(nread < 0) {
  294. failf(data, "read: %s", strerror(errno));
  295. rc = -1;
  296. }
  297. if(nread <= 0)
  298. break;
  299. what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
  300. }
  301. return rc;
  302. }
  303. static ssize_t qsossl_send(struct connectdata * conn, int sockindex,
  304. const void * mem, size_t len, CURLcode * curlcode)
  305. {
  306. /* SSL_Write() is said to return 'int' while write() and send() returns
  307. 'size_t' */
  308. int rc;
  309. rc = SSL_Write(conn->ssl[sockindex].handle, (void *) mem, (int) len);
  310. if(rc < 0) {
  311. switch(rc) {
  312. case SSL_ERROR_BAD_STATE:
  313. /* The operation did not complete; the same SSL I/O function
  314. should be called again later. This is basically an EWOULDBLOCK
  315. equivalent. */
  316. *curlcode = CURLE_AGAIN;
  317. return -1;
  318. case SSL_ERROR_IO:
  319. switch (errno) {
  320. case EWOULDBLOCK:
  321. case EINTR:
  322. *curlcode = CURLE_AGAIN;
  323. return -1;
  324. }
  325. failf(conn->data, "SSL_Write() I/O error: %s", strerror(errno));
  326. *curlcode = CURLE_SEND_ERROR;
  327. return -1;
  328. }
  329. /* An SSL error. */
  330. failf(conn->data, "SSL_Write() returned error %s",
  331. SSL_Strerror(rc, NULL));
  332. *curlcode = CURLE_SEND_ERROR;
  333. return -1;
  334. }
  335. return (ssize_t) rc; /* number of bytes */
  336. }
  337. static ssize_t qsossl_recv(struct connectdata * conn, int num, char * buf,
  338. size_t buffersize, CURLcode * curlcode)
  339. {
  340. char error_buffer[120]; /* OpenSSL documents that this must be at
  341. least 120 bytes long. */
  342. unsigned long sslerror;
  343. int buffsize;
  344. int nread;
  345. buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
  346. nread = SSL_Read(conn->ssl[num].handle, buf, buffsize);
  347. if(nread < 0) {
  348. /* failed SSL_read */
  349. switch (nread) {
  350. case SSL_ERROR_BAD_STATE:
  351. /* there's data pending, re-invoke SSL_Read(). */
  352. *curlcode = CURLE_AGAIN;
  353. return -1;
  354. case SSL_ERROR_IO:
  355. switch (errno) {
  356. case EWOULDBLOCK:
  357. *curlcode = CURLE_AGAIN;
  358. return -1;
  359. }
  360. failf(conn->data, "SSL_Read() I/O error: %s", strerror(errno));
  361. *curlcode = CURLE_RECV_ERROR;
  362. return -1;
  363. default:
  364. failf(conn->data, "SSL read error: %s", SSL_Strerror(nread, NULL));
  365. *curlcode = CURLE_RECV_ERROR;
  366. return -1;
  367. }
  368. }
  369. return (ssize_t) nread;
  370. }
  371. size_t Curl_qsossl_version(char * buffer, size_t size)
  372. {
  373. strncpy(buffer, "IBM OS/400 SSL", size);
  374. return strlen(buffer);
  375. }
  376. int Curl_qsossl_check_cxn(struct connectdata * cxn)
  377. {
  378. int err;
  379. int errlen;
  380. /* The only thing that can be tested here is at the socket level. */
  381. if(!cxn->ssl[FIRSTSOCKET].handle)
  382. return 0; /* connection has been closed */
  383. err = 0;
  384. errlen = sizeof err;
  385. if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
  386. (unsigned char *) &err, &errlen) ||
  387. errlen != sizeof err || err)
  388. return 0; /* connection has been closed */
  389. return -1; /* connection status unknown */
  390. }
  391. #endif /* USE_QSOSSL */