qssl.c 11 KB

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