conn-ssl.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. *
  4. * SSL wrapper functions.
  5. * Copyright (c) 2005-2008 Florian Westphal <fw@strlen.de>
  6. */
  7. #include "portab.h"
  8. #include "imp.h"
  9. #include "conf-ssl.h"
  10. #ifdef SSL_SUPPORT
  11. #include "io.h"
  12. #include <assert.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <errno.h>
  17. #define CONN_MODULE
  18. #include "conn.h"
  19. #include "conf.h"
  20. #include "conn-func.h"
  21. #include "conn-ssl.h"
  22. #include "log.h"
  23. #include "exp.h"
  24. #include "defines.h"
  25. extern struct SSLOptions Conf_SSLOptions;
  26. #ifdef HAVE_LIBSSL
  27. #include <openssl/err.h>
  28. #include <openssl/rand.h>
  29. static SSL_CTX * ssl_ctx;
  30. static DH *dh_params;
  31. static bool ConnSSL_LoadServerKey_openssl PARAMS(( SSL_CTX *c ));
  32. #endif
  33. #ifdef HAVE_LIBGNUTLS
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include <fcntl.h>
  37. #include <unistd.h>
  38. #include <gnutls/x509.h>
  39. #define DH_BITS 1024
  40. static gnutls_certificate_credentials_t x509_cred;
  41. static gnutls_dh_params_t dh_params;
  42. static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void ));
  43. #endif
  44. static bool ConnSSL_Init_SSL PARAMS(( CONNECTION *c ));
  45. static int ConnectAccept PARAMS(( CONNECTION *c, bool connect ));
  46. static int ConnSSL_HandleError PARAMS(( CONNECTION *c, const int code, const char *fname ));
  47. #ifdef HAVE_LIBGNUTLS
  48. static char * openreadclose(const char *name, size_t *len)
  49. {
  50. char *buf = NULL;
  51. struct stat s;
  52. ssize_t br;
  53. int fd = open(name, O_RDONLY);
  54. if (fd < 0) {
  55. Log(LOG_ERR, "Could not open %s: %s", name, strerror(errno));
  56. return NULL;
  57. }
  58. if (fstat(fd, &s)) {
  59. Log(LOG_ERR, "Could not fstat %s: %s", name, strerror(errno));
  60. goto out;
  61. }
  62. if (!S_ISREG(s.st_mode)) {
  63. Log(LOG_ERR, "%s: Not a regular file", name);
  64. goto out;
  65. }
  66. if (s.st_size <= 0) {
  67. Log(LOG_ERR, "%s: invalid file length (size %ld <= 0)", name, (long) s.st_size);
  68. goto out;
  69. }
  70. buf = malloc(s.st_size);
  71. if (!buf) {
  72. Log(LOG_ERR, "Could not malloc %lu bytes for file %s: %s", s.st_size, name, strerror(errno));
  73. goto out;
  74. }
  75. br = read(fd, buf, s.st_size);
  76. if (br != (ssize_t)s.st_size) {
  77. Log(LOG_ERR, "Could not read file %s: read returned %ld, expected %ld: %s",
  78. name, (long) br, (long) s.st_size, br == -1 ? strerror(errno):"short read?!");
  79. memset(buf, 0, s.st_size);
  80. free(buf);
  81. buf = NULL;
  82. } else {
  83. *len = br;
  84. }
  85. out:
  86. close(fd);
  87. return buf;
  88. }
  89. #endif
  90. #ifdef HAVE_LIBSSL
  91. static void
  92. LogOpenSSLError( const char *msg, const char *msg2 )
  93. {
  94. unsigned long err = ERR_get_error();
  95. char * errmsg = err ? ERR_error_string(err, NULL) : "Unable to determine error";
  96. if (!msg) msg = "SSL Error";
  97. if (msg2)
  98. Log( LOG_ERR, "%s: %s: %s", msg, msg2, errmsg);
  99. else
  100. Log( LOG_ERR, "%s: %s", msg, errmsg);
  101. }
  102. static int
  103. pem_passwd_cb(char *buf, int size, int rwflag, void *password)
  104. {
  105. array *pass = password;
  106. int passlen;
  107. (void)rwflag; /* rwflag is unused if DEBUG is not set. */
  108. assert(rwflag == 0); /* 0 -> callback used for decryption.
  109. * See SSL_CTX_set_default_passwd_cb(3) */
  110. passlen = (int) array_bytes(pass);
  111. LogDebug("pem_passwd_cb buf size %d, array size %d", size, passlen);
  112. assert(passlen >= 0);
  113. if (passlen <= 0) {
  114. Log(LOG_ERR, "pem_passwd_cb: password required, but not set");
  115. return 0;
  116. }
  117. size = passlen > size ? size : passlen;
  118. memcpy(buf, (char *)(array_start(pass)), size);
  119. return size;
  120. }
  121. #endif
  122. static bool
  123. Load_DH_params(void)
  124. {
  125. #ifdef HAVE_LIBSSL
  126. FILE *fp;
  127. bool ret = true;
  128. if (!Conf_SSLOptions.DHFile) {
  129. Log(LOG_NOTICE, "Configuration option \"SSLDHFile\" not set!");
  130. return false;
  131. }
  132. fp = fopen(Conf_SSLOptions.DHFile, "r");
  133. if (!fp) {
  134. Log(LOG_ERR, "%s: %s", Conf_SSLOptions.DHFile, strerror(errno));
  135. return false;
  136. }
  137. dh_params = PEM_read_DHparams(fp, NULL, NULL, NULL);
  138. if (!dh_params) {
  139. Log(LOG_ERR, "%s: PEM_read_DHparams failed!",
  140. Conf_SSLOptions.DHFile);
  141. ret = false;
  142. }
  143. fclose(fp);
  144. return ret;
  145. #endif
  146. #ifdef HAVE_LIBGNUTLS
  147. bool need_dhgenerate = true;
  148. int err;
  149. gnutls_dh_params_t tmp_dh_params;
  150. err = gnutls_dh_params_init(&tmp_dh_params);
  151. if (err < 0) {
  152. Log(LOG_ERR, "gnutls_dh_params_init: %s", gnutls_strerror(err));
  153. return false;
  154. }
  155. if (Conf_SSLOptions.DHFile) {
  156. gnutls_datum_t dhparms;
  157. size_t size;
  158. dhparms.data = (unsigned char *) openreadclose(Conf_SSLOptions.DHFile, &size);
  159. if (dhparms.data) {
  160. dhparms.size = size;
  161. err = gnutls_dh_params_import_pkcs3(tmp_dh_params, &dhparms, GNUTLS_X509_FMT_PEM);
  162. if (err == 0)
  163. need_dhgenerate = false;
  164. else
  165. Log(LOG_ERR, "gnutls_dh_params_init: %s", gnutls_strerror(err));
  166. memset(dhparms.data, 0, size);
  167. free(dhparms.data);
  168. }
  169. }
  170. if (need_dhgenerate) {
  171. Log(LOG_WARNING,
  172. "SSLDHFile not set, generating %u bit DH parameters. This may take a while ...",
  173. DH_BITS);
  174. err = gnutls_dh_params_generate2(tmp_dh_params, DH_BITS);
  175. if (err < 0) {
  176. Log(LOG_ERR, "gnutls_dh_params_generate2: %s", gnutls_strerror(err));
  177. return false;
  178. }
  179. }
  180. dh_params = tmp_dh_params;
  181. return true;
  182. #endif
  183. }
  184. void ConnSSL_Free(CONNECTION *c)
  185. {
  186. #ifdef HAVE_LIBSSL
  187. SSL *ssl = c->ssl_state.ssl;
  188. if (ssl) {
  189. SSL_shutdown(ssl);
  190. SSL_free(ssl);
  191. c->ssl_state.ssl = NULL;
  192. }
  193. #endif
  194. #ifdef HAVE_LIBGNUTLS
  195. gnutls_session_t sess = c->ssl_state.gnutls_session;
  196. if (Conn_OPTION_ISSET(c, CONN_SSL)) {
  197. gnutls_bye(sess, GNUTLS_SHUT_RDWR);
  198. gnutls_deinit(sess);
  199. }
  200. #endif
  201. assert(Conn_OPTION_ISSET(c, CONN_SSL));
  202. /* can't just set bitmask to 0 -- there are other, non-ssl related flags, e.g. CONN_ZIP. */
  203. Conn_OPTION_DEL(c, CONN_SSL_FLAGS_ALL);
  204. }
  205. bool
  206. ConnSSL_InitLibrary( void )
  207. {
  208. #ifdef HAVE_LIBSSL
  209. SSL_CTX *newctx;
  210. if (!ssl_ctx) {
  211. SSL_library_init();
  212. SSL_load_error_strings();
  213. }
  214. if (!RAND_status()) {
  215. Log(LOG_ERR, "OpenSSL PRNG not seeded: /dev/urandom missing?");
  216. /*
  217. * it is probably best to fail and let the user install EGD or a similar program if no kernel random device is available.
  218. * According to OpenSSL RAND_egd(3): "The automatic query of /var/run/egd-pool et al was added in OpenSSL 0.9.7";
  219. * so it makes little sense to deal with PRNGD seeding ourselves.
  220. */
  221. return false;
  222. }
  223. newctx = SSL_CTX_new(SSLv23_method());
  224. if (!newctx) {
  225. LogOpenSSLError("SSL_CTX_new()", NULL);
  226. return false;
  227. }
  228. if (!ConnSSL_LoadServerKey_openssl(newctx))
  229. goto out;
  230. SSL_CTX_set_options(newctx, SSL_OP_SINGLE_DH_USE|SSL_OP_NO_SSLv2);
  231. SSL_CTX_set_mode(newctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
  232. SSL_CTX_free(ssl_ctx);
  233. ssl_ctx = newctx;
  234. Log(LOG_INFO, "%s initialized.", SSLeay_version(SSLEAY_VERSION));
  235. return true;
  236. out:
  237. SSL_CTX_free(newctx);
  238. return false;
  239. #endif
  240. #ifdef HAVE_LIBGNUTLS
  241. int err;
  242. static bool initialized;
  243. if (initialized) /* TODO: cannot reload gnutls keys: can't simply free x509 context -- it may still be in use */
  244. return false;
  245. err = gnutls_global_init();
  246. if (err) {
  247. Log(LOG_ERR, "gnutls_global_init(): %s", gnutls_strerror(err));
  248. return false;
  249. }
  250. if (!ConnSSL_LoadServerKey_gnutls())
  251. return false;
  252. Log(LOG_INFO, "gnutls %s initialized.", gnutls_check_version(NULL));
  253. initialized = true;
  254. return true;
  255. #endif
  256. }
  257. #ifdef HAVE_LIBGNUTLS
  258. static bool
  259. ConnSSL_LoadServerKey_gnutls(void)
  260. {
  261. int err;
  262. const char *cert_file;
  263. err = gnutls_certificate_allocate_credentials(&x509_cred);
  264. if (err < 0) {
  265. Log(LOG_ERR, "gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err));
  266. return false;
  267. }
  268. cert_file = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile;
  269. if (!cert_file) {
  270. Log(LOG_NOTICE, "No SSL server key configured, SSL disabled.");
  271. return false;
  272. }
  273. if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
  274. Log(LOG_WARNING,
  275. "Ignoring KeyFilePassword: Not supported by GNUTLS.");
  276. if (!Load_DH_params())
  277. return false;
  278. gnutls_certificate_set_dh_params(x509_cred, dh_params);
  279. err = gnutls_certificate_set_x509_key_file(x509_cred, cert_file, Conf_SSLOptions.KeyFile, GNUTLS_X509_FMT_PEM);
  280. if (err < 0) {
  281. Log(LOG_ERR, "gnutls_certificate_set_x509_key_file (cert %s, key %s): %s",
  282. cert_file, Conf_SSLOptions.KeyFile ? Conf_SSLOptions.KeyFile : "(NULL)", gnutls_strerror(err));
  283. return false;
  284. }
  285. return true;
  286. }
  287. #endif
  288. #ifdef HAVE_LIBSSL
  289. static bool
  290. ConnSSL_LoadServerKey_openssl(SSL_CTX *ctx)
  291. {
  292. char *cert_key;
  293. assert(ctx);
  294. if (!Conf_SSLOptions.KeyFile) {
  295. Log(LOG_NOTICE, "No SSL server key configured, SSL disabled.");
  296. return false;
  297. }
  298. SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
  299. SSL_CTX_set_default_passwd_cb_userdata(ctx, &Conf_SSLOptions.KeyFilePassword);
  300. if (SSL_CTX_use_PrivateKey_file(ctx, Conf_SSLOptions.KeyFile, SSL_FILETYPE_PEM) != 1) {
  301. array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
  302. LogOpenSSLError("SSL_CTX_use_PrivateKey_file", Conf_SSLOptions.KeyFile);
  303. return false;
  304. }
  305. cert_key = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile;
  306. if (SSL_CTX_use_certificate_chain_file(ctx, cert_key) != 1) {
  307. array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
  308. LogOpenSSLError("SSL_CTX_use_certificate_file", cert_key);
  309. return false;
  310. }
  311. array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
  312. if (!SSL_CTX_check_private_key(ctx)) {
  313. LogOpenSSLError("Server Private Key does not match certificate", NULL);
  314. return false;
  315. }
  316. if (Load_DH_params()) {
  317. if (SSL_CTX_set_tmp_dh(ctx, dh_params) != 1)
  318. LogOpenSSLError("Error setting DH Parameters", Conf_SSLOptions.DHFile);
  319. /* don't return false here: the non-DH modes will still work */
  320. DH_free(dh_params);
  321. dh_params = NULL;
  322. }
  323. return true;
  324. }
  325. #endif
  326. static bool
  327. ConnSSL_Init_SSL(CONNECTION *c)
  328. {
  329. int ret;
  330. assert(c != NULL);
  331. #ifdef HAVE_LIBSSL
  332. if (!ssl_ctx) {
  333. Log(LOG_ERR, "Cannot init ssl_ctx: OpenSSL initialization failed at startup");
  334. return false;
  335. }
  336. assert(c->ssl_state.ssl == NULL);
  337. c->ssl_state.ssl = SSL_new(ssl_ctx);
  338. if (!c->ssl_state.ssl) {
  339. LogOpenSSLError("SSL_new()", NULL);
  340. return false;
  341. }
  342. ret = SSL_set_fd(c->ssl_state.ssl, c->sock);
  343. if (ret != 1) {
  344. LogOpenSSLError("SSL_set_fd()", NULL);
  345. ConnSSL_Free(c);
  346. return false;
  347. }
  348. #endif
  349. #ifdef HAVE_LIBGNUTLS
  350. ret = gnutls_set_default_priority(c->ssl_state.gnutls_session);
  351. if (ret < 0) {
  352. Log(LOG_ERR, "gnutls_set_default_priority: %s", gnutls_strerror(ret));
  353. ConnSSL_Free(c);
  354. return false;
  355. }
  356. /*
  357. * The intermediate (long) cast is here to avoid a warning like:
  358. * "cast to pointer from integer of different size" on 64-bit platforms.
  359. * There doesn't seem to be an alternate GNUTLS API we could use instead, see e.g.
  360. * http://www.mail-archive.com/help-gnutls@gnu.org/msg00286.html
  361. */
  362. gnutls_transport_set_ptr(c->ssl_state.gnutls_session, (gnutls_transport_ptr_t) (long) c->sock);
  363. ret = gnutls_credentials_set(c->ssl_state.gnutls_session, GNUTLS_CRD_CERTIFICATE, x509_cred);
  364. if (ret < 0) {
  365. Log(LOG_ERR, "gnutls_credentials_set: %s", gnutls_strerror(ret));
  366. ConnSSL_Free(c);
  367. return false;
  368. }
  369. gnutls_dh_set_prime_bits(c->ssl_state.gnutls_session, DH_BITS);
  370. #endif
  371. Conn_OPTION_ADD(c, CONN_SSL);
  372. return true;
  373. }
  374. bool
  375. ConnSSL_PrepareConnect(CONNECTION *c, UNUSED CONF_SERVER *s)
  376. {
  377. bool ret;
  378. #ifdef HAVE_LIBGNUTLS
  379. int err;
  380. err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_CLIENT);
  381. if (err) {
  382. Log(LOG_ERR, "gnutls_init: %s", gnutls_strerror(err));
  383. return false;
  384. }
  385. #endif
  386. ret = ConnSSL_Init_SSL(c);
  387. if (!ret)
  388. return false;
  389. Conn_OPTION_ADD(c, CONN_SSL_CONNECT);
  390. #ifdef HAVE_LIBSSL
  391. assert(c->ssl_state.ssl);
  392. SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_NONE, NULL);
  393. #endif
  394. return true;
  395. }
  396. /*
  397. Check an Handle Error return code after failed calls to ssl/tls functions.
  398. OpenSSL:
  399. SSL_connect(), SSL_accept(), SSL_do_handshake(), SSL_read(), SSL_peek(), or SSL_write() on ssl.
  400. GNUTLS:
  401. gnutlsssl_read(), gnutls_write() or gnutls_handshake().
  402. Return: -1 on fatal error, 0 if we can try again later.
  403. */
  404. static int
  405. ConnSSL_HandleError( CONNECTION *c, const int code, const char *fname )
  406. {
  407. #ifdef HAVE_LIBSSL
  408. int ret = SSL_ERROR_SYSCALL;
  409. unsigned long sslerr;
  410. int real_errno = errno;
  411. ret = SSL_get_error(c->ssl_state.ssl, code);
  412. switch (ret) {
  413. case SSL_ERROR_WANT_READ:
  414. io_event_del(c->sock, IO_WANTWRITE);
  415. Conn_OPTION_ADD(c, CONN_SSL_WANT_READ);
  416. return 0; /* try again later */
  417. case SSL_ERROR_WANT_WRITE:
  418. io_event_del(c->sock, IO_WANTREAD);
  419. Conn_OPTION_ADD(c, CONN_SSL_WANT_WRITE); /* fall through */
  420. case SSL_ERROR_NONE:
  421. return 0; /* try again later */
  422. case SSL_ERROR_ZERO_RETURN:
  423. LogDebug("TLS/SSL connection shut down normally");
  424. break;
  425. /*
  426. SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT, SSL_ERROR_WANT_X509_LOOKUP
  427. */
  428. case SSL_ERROR_SYSCALL:
  429. sslerr = ERR_get_error();
  430. if (sslerr) {
  431. Log( LOG_ERR, "%s: %s", fname, ERR_error_string(sslerr, NULL ));
  432. } else {
  433. switch (code) { /* EOF that violated protocol */
  434. case 0:
  435. Log(LOG_ERR, "%s: Client Disconnected", fname );
  436. break;
  437. case -1: /* low level socket I/O error, check errno */
  438. Log(LOG_ERR, "%s: %s", fname, strerror(real_errno));
  439. }
  440. }
  441. break;
  442. case SSL_ERROR_SSL:
  443. LogOpenSSLError("TLS/SSL Protocol Error", fname);
  444. break;
  445. default:
  446. Log( LOG_ERR, "%s: Unknown error %d!", fname, ret);
  447. }
  448. ConnSSL_Free(c);
  449. return -1;
  450. #endif
  451. #ifdef HAVE_LIBGNUTLS
  452. switch (code) {
  453. case GNUTLS_E_AGAIN:
  454. case GNUTLS_E_INTERRUPTED:
  455. if (gnutls_record_get_direction(c->ssl_state.gnutls_session)) {
  456. Conn_OPTION_ADD(c, CONN_SSL_WANT_WRITE);
  457. io_event_del(c->sock, IO_WANTREAD);
  458. } else {
  459. Conn_OPTION_ADD(c, CONN_SSL_WANT_READ);
  460. io_event_del(c->sock, IO_WANTWRITE);
  461. }
  462. break;
  463. default:
  464. assert(code < 0);
  465. if (gnutls_error_is_fatal(code)) {
  466. Log(LOG_ERR, "%s: %s", fname, gnutls_strerror(code));
  467. ConnSSL_Free(c);
  468. return -1;
  469. }
  470. }
  471. return 0;
  472. #endif
  473. }
  474. static void
  475. ConnSSL_LogCertInfo( CONNECTION *c )
  476. {
  477. #ifdef HAVE_LIBSSL
  478. SSL *ssl = c->ssl_state.ssl;
  479. assert(ssl);
  480. Log(LOG_INFO, "New %s connection using cipher %s on socket %d.",
  481. SSL_get_version(ssl), SSL_get_cipher(ssl), c->sock);
  482. #endif
  483. #ifdef HAVE_LIBGNUTLS
  484. gnutls_session_t sess = c->ssl_state.gnutls_session;
  485. gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess);
  486. Log(LOG_INFO, "New %s connection using cipher %s-%s on socket %d.",
  487. gnutls_protocol_get_name(gnutls_protocol_get_version(sess)),
  488. gnutls_cipher_get_name(cipher),
  489. gnutls_mac_get_name(gnutls_mac_get(sess)), c->sock);
  490. #endif
  491. }
  492. /*
  493. Accept incoming SSL connection.
  494. Return Values:
  495. 1: SSL Connection established
  496. 0: try again
  497. -1: SSL Connection not established due to fatal error.
  498. */
  499. int
  500. ConnSSL_Accept( CONNECTION *c )
  501. {
  502. assert(c != NULL);
  503. if (!Conn_OPTION_ISSET(c, CONN_SSL)) {
  504. #ifdef HAVE_LIBGNUTLS
  505. int err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_SERVER);
  506. if (err) {
  507. Log(LOG_ERR, "gnutls_init: %s", gnutls_strerror(err));
  508. return false;
  509. }
  510. #endif
  511. LogDebug("ConnSSL_Accept: Initializing SSL data");
  512. if (!ConnSSL_Init_SSL(c))
  513. return -1;
  514. }
  515. return ConnectAccept(c, false );
  516. }
  517. int
  518. ConnSSL_Connect( CONNECTION *c )
  519. {
  520. assert(c != NULL);
  521. #ifdef HAVE_LIBSSL
  522. assert(c->ssl_state.ssl);
  523. #endif
  524. assert(Conn_OPTION_ISSET(c, CONN_SSL));
  525. return ConnectAccept(c, true);
  526. }
  527. /* accept/connect wrapper. if connect is true, connect to peer, otherwise wait for incoming connection */
  528. static int
  529. ConnectAccept( CONNECTION *c, bool connect)
  530. {
  531. int ret;
  532. #ifdef HAVE_LIBSSL
  533. SSL *ssl = c->ssl_state.ssl;
  534. assert(ssl != NULL);
  535. ret = connect ? SSL_connect(ssl) : SSL_accept(ssl);
  536. if (1 != ret)
  537. return ConnSSL_HandleError(c, ret, connect ? "SSL_connect": "SSL_accept");
  538. #endif
  539. #ifdef HAVE_LIBGNUTLS
  540. (void) connect;
  541. ret = gnutls_handshake(c->ssl_state.gnutls_session);
  542. if (ret)
  543. return ConnSSL_HandleError(c, ret, "gnutls_handshake");
  544. #endif /* _GNUTLS */
  545. Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT));
  546. ConnSSL_LogCertInfo(c);
  547. return 1;
  548. }
  549. ssize_t
  550. ConnSSL_Write(CONNECTION *c, const void *buf, size_t count)
  551. {
  552. ssize_t bw;
  553. Conn_OPTION_DEL(c, CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ);
  554. assert(count > 0);
  555. #ifdef HAVE_LIBSSL
  556. bw = (ssize_t) SSL_write(c->ssl_state.ssl, buf, count);
  557. #endif
  558. #ifdef HAVE_LIBGNUTLS
  559. bw = gnutls_write(c->ssl_state.gnutls_session, buf, count);
  560. #endif
  561. if (bw > 0)
  562. return bw;
  563. if (ConnSSL_HandleError( c, bw, "ConnSSL_Write") == 0)
  564. errno = EAGAIN; /* try again */
  565. return -1;
  566. }
  567. ssize_t
  568. ConnSSL_Read(CONNECTION *c, void * buf, size_t count)
  569. {
  570. ssize_t br;
  571. Conn_OPTION_DEL(c, CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ);
  572. #ifdef HAVE_LIBSSL
  573. br = (ssize_t) SSL_read(c->ssl_state.ssl, buf, count);
  574. if (br > 0) /* on EOF we have to call ConnSSL_HandleError(), see SSL_read(3) */
  575. return br;
  576. #endif
  577. #ifdef HAVE_LIBGNUTLS
  578. br = gnutls_read(c->ssl_state.gnutls_session, buf, count);
  579. if (br >= 0) /* on EOF we must _not_ call ConnSSL_HandleError, see gnutls_record_recv(3) */
  580. return br;
  581. #endif
  582. /* error on read: switch ConnSSL_HandleError() return values -> 0 is "try again", so return -1 and set EAGAIN */
  583. if (ConnSSL_HandleError(c, br, "ConnSSL_Read") == 0) {
  584. errno = EAGAIN;
  585. return -1;
  586. }
  587. return 0;
  588. }
  589. bool
  590. ConnSSL_GetCipherInfo(CONNECTION *c, char *buf, size_t len)
  591. {
  592. #ifdef HAVE_LIBSSL
  593. char *nl;
  594. SSL *ssl = c->ssl_state.ssl;
  595. if (!ssl)
  596. return false;
  597. *buf = 0;
  598. SSL_CIPHER_description(SSL_get_current_cipher(ssl), buf, len);
  599. nl = strchr(buf, '\n');
  600. if (nl)
  601. *nl = 0;
  602. return true;
  603. #endif
  604. #ifdef HAVE_LIBGNUTLS
  605. if (Conn_OPTION_ISSET(c, CONN_SSL)) {
  606. const char *name_cipher, *name_mac, *name_proto, *name_keyexchange;
  607. unsigned keysize;
  608. gnutls_session_t sess = c->ssl_state.gnutls_session;
  609. gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess);
  610. name_cipher = gnutls_cipher_get_name(cipher);
  611. name_mac = gnutls_mac_get_name(gnutls_mac_get(sess));
  612. keysize = gnutls_cipher_get_key_size(cipher) * 8;
  613. name_proto = gnutls_protocol_get_name(gnutls_protocol_get_version(sess));
  614. name_keyexchange = gnutls_kx_get_name(gnutls_kx_get(sess));
  615. return snprintf(buf, len, "%s-%s%15s Kx=%s Enc=%s(%u) Mac=%s",
  616. name_cipher, name_mac, name_proto, name_keyexchange, name_cipher, keysize, name_mac) > 0;
  617. }
  618. return false;
  619. #endif
  620. }
  621. #endif /* SSL_SUPPORT */
  622. /* -eof- */