conn-ssl.c 18 KB

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