conn-ssl.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2005-2008 Florian Westphal (fw@strlen.de).
  4. * Copyright (c)2008-2014 Alexander Barton (alex@barton.de) and Contributors.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. * Please read the file COPYING, README and AUTHORS for more information.
  11. */
  12. #include "portab.h"
  13. /**
  14. * @file
  15. * SSL wrapper functions
  16. */
  17. #include "conf-ssl.h"
  18. #ifdef SSL_SUPPORT
  19. #include "io.h"
  20. #include <assert.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <errno.h>
  25. #define CONN_MODULE
  26. #include "conn.h"
  27. #include "conf.h"
  28. #include "conn-func.h"
  29. #include "conn-ssl.h"
  30. #include "log.h"
  31. #include "defines.h"
  32. extern struct SSLOptions Conf_SSLOptions;
  33. #ifdef HAVE_LIBSSL
  34. #include <openssl/err.h>
  35. #include <openssl/rand.h>
  36. #include <openssl/dh.h>
  37. static SSL_CTX * ssl_ctx;
  38. static DH *dh_params;
  39. static bool ConnSSL_LoadServerKey_openssl PARAMS(( SSL_CTX *c ));
  40. #endif
  41. #ifdef HAVE_LIBGNUTLS
  42. #include <sys/types.h>
  43. #include <sys/stat.h>
  44. #include <fcntl.h>
  45. #include <unistd.h>
  46. #include <gnutls/x509.h>
  47. #define DH_BITS 2048
  48. #define DH_BITS_MIN 1024
  49. #define MAX_HASH_SIZE 64 /* from gnutls-int.h */
  50. typedef struct {
  51. int refcnt;
  52. gnutls_certificate_credentials_t x509_cred;
  53. gnutls_dh_params_t dh_params;
  54. } x509_cred_slot;
  55. static array x509_creds = INIT_ARRAY;
  56. static size_t x509_cred_idx;
  57. static gnutls_dh_params_t dh_params;
  58. static gnutls_priority_t priorities_cache = NULL;
  59. static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void ));
  60. #endif
  61. #define SHA256_STRING_LEN (32 * 2 + 1)
  62. static bool ConnSSL_Init_SSL PARAMS(( CONNECTION *c ));
  63. static int ConnectAccept PARAMS(( CONNECTION *c, bool connect ));
  64. static int ConnSSL_HandleError PARAMS(( CONNECTION *c, const int code, const char *fname ));
  65. #ifdef HAVE_LIBGNUTLS
  66. static char * openreadclose(const char *name, size_t *len)
  67. {
  68. char *buf = NULL;
  69. struct stat s;
  70. ssize_t br;
  71. int fd = open(name, O_RDONLY);
  72. if (fd < 0) {
  73. Log(LOG_ERR, "Could not open %s: %s", name, strerror(errno));
  74. return NULL;
  75. }
  76. if (fstat(fd, &s)) {
  77. Log(LOG_ERR, "Could not fstat %s: %s", name, strerror(errno));
  78. goto out;
  79. }
  80. if (!S_ISREG(s.st_mode)) {
  81. Log(LOG_ERR, "%s: Not a regular file", name);
  82. goto out;
  83. }
  84. if (s.st_size <= 0) {
  85. Log(LOG_ERR, "%s: invalid file length (size %ld <= 0)", name, (long) s.st_size);
  86. goto out;
  87. }
  88. buf = malloc(s.st_size);
  89. if (!buf) {
  90. Log(LOG_ERR, "Could not malloc %lu bytes for file %s: %s", s.st_size, name, strerror(errno));
  91. goto out;
  92. }
  93. br = read(fd, buf, s.st_size);
  94. if (br != (ssize_t)s.st_size) {
  95. Log(LOG_ERR, "Could not read file %s: read returned %ld, expected %ld: %s",
  96. name, (long) br, (long) s.st_size, br == -1 ? strerror(errno):"short read?!");
  97. memset(buf, 0, s.st_size);
  98. free(buf);
  99. buf = NULL;
  100. } else {
  101. *len = br;
  102. }
  103. out:
  104. close(fd);
  105. return buf;
  106. }
  107. #endif
  108. #ifdef HAVE_LIBSSL
  109. /**
  110. * Log OpenSSL error message.
  111. *
  112. * @param msg The error message.
  113. * @param info Additional information text or NULL.
  114. */
  115. static void
  116. LogOpenSSLError(const char *error, const char *info)
  117. {
  118. unsigned long err = ERR_get_error();
  119. char * errmsg = err
  120. ? ERR_error_string(err, NULL)
  121. : "Unable to determine error";
  122. assert(error != NULL);
  123. if (info)
  124. Log(LOG_ERR, "%s: %s (%s)", error, info, errmsg);
  125. else
  126. Log(LOG_ERR, "%s: %s", error, errmsg);
  127. }
  128. static int
  129. pem_passwd_cb(char *buf, int size, int rwflag, void *password)
  130. {
  131. array *pass = password;
  132. int passlen;
  133. (void)rwflag; /* rwflag is unused if DEBUG is not set. */
  134. assert(rwflag == 0); /* 0 -> callback used for decryption.
  135. * See SSL_CTX_set_default_passwd_cb(3) */
  136. passlen = (int) array_bytes(pass);
  137. LogDebug("pem_passwd_cb buf size %d, array size %d", size, passlen);
  138. assert(passlen >= 0);
  139. if (passlen <= 0) {
  140. Log(LOG_ERR, "PEM password required but not set [in pem_passwd_cb()]!");
  141. return 0;
  142. }
  143. size = passlen > size ? size : passlen;
  144. memcpy(buf, (char *)(array_start(pass)), size);
  145. return size;
  146. }
  147. static int
  148. Verify_openssl(UNUSED int preverify_ok, UNUSED X509_STORE_CTX *x509_ctx)
  149. {
  150. return 1;
  151. }
  152. #endif
  153. static bool
  154. Load_DH_params(void)
  155. {
  156. #ifdef HAVE_LIBSSL
  157. FILE *fp;
  158. bool ret = true;
  159. if (!Conf_SSLOptions.DHFile) {
  160. Log(LOG_NOTICE, "Configuration option \"DHFile\" not set!");
  161. return false;
  162. }
  163. fp = fopen(Conf_SSLOptions.DHFile, "r");
  164. if (!fp) {
  165. Log(LOG_ERR, "%s: %s", Conf_SSLOptions.DHFile, strerror(errno));
  166. return false;
  167. }
  168. dh_params = PEM_read_DHparams(fp, NULL, NULL, NULL);
  169. if (!dh_params) {
  170. Log(LOG_ERR, "%s: Failed to read SSL DH parameters!",
  171. Conf_SSLOptions.DHFile);
  172. ret = false;
  173. }
  174. fclose(fp);
  175. return ret;
  176. #endif
  177. #ifdef HAVE_LIBGNUTLS
  178. bool need_dhgenerate = true;
  179. int err;
  180. gnutls_dh_params_t tmp_dh_params;
  181. err = gnutls_dh_params_init(&tmp_dh_params);
  182. if (err < 0) {
  183. Log(LOG_ERR, "Failed to initialize SSL DH parameters: %s",
  184. gnutls_strerror(err));
  185. return false;
  186. }
  187. if (Conf_SSLOptions.DHFile) {
  188. gnutls_datum_t dhparms;
  189. size_t size;
  190. dhparms.data = (unsigned char *) openreadclose(Conf_SSLOptions.DHFile, &size);
  191. if (dhparms.data) {
  192. dhparms.size = size;
  193. err = gnutls_dh_params_import_pkcs3(tmp_dh_params, &dhparms, GNUTLS_X509_FMT_PEM);
  194. if (err == 0)
  195. need_dhgenerate = false;
  196. else
  197. Log(LOG_ERR,
  198. "Failed to initialize SSL DH parameters: %s",
  199. gnutls_strerror(err));
  200. memset(dhparms.data, 0, size);
  201. free(dhparms.data);
  202. }
  203. }
  204. if (need_dhgenerate) {
  205. Log(LOG_WARNING,
  206. "DHFile not set, generating %u bit DH parameters. This may take a while ...",
  207. DH_BITS);
  208. err = gnutls_dh_params_generate2(tmp_dh_params, DH_BITS);
  209. if (err < 0) {
  210. Log(LOG_ERR, "Failed to generate SSL DH parameters: %s",
  211. gnutls_strerror(err));
  212. return false;
  213. }
  214. }
  215. dh_params = tmp_dh_params;
  216. return true;
  217. #endif
  218. }
  219. void ConnSSL_Free(CONNECTION *c)
  220. {
  221. #ifdef HAVE_LIBSSL
  222. SSL *ssl = c->ssl_state.ssl;
  223. if (ssl) {
  224. SSL_shutdown(ssl);
  225. SSL_free(ssl);
  226. c->ssl_state.ssl = NULL;
  227. if (c->ssl_state.fingerprint) {
  228. free(c->ssl_state.fingerprint);
  229. c->ssl_state.fingerprint = NULL;
  230. }
  231. }
  232. #endif
  233. #ifdef HAVE_LIBGNUTLS
  234. gnutls_session_t sess = c->ssl_state.gnutls_session;
  235. if (Conn_OPTION_ISSET(c, CONN_SSL)) {
  236. gnutls_bye(sess, GNUTLS_SHUT_RDWR);
  237. gnutls_deinit(sess);
  238. }
  239. x509_cred_slot *slot = array_get(&x509_creds, sizeof(x509_cred_slot), c->ssl_state.x509_cred_idx);
  240. assert(slot != NULL);
  241. assert(slot->refcnt > 0);
  242. assert(slot->x509_cred != NULL);
  243. slot->refcnt--;
  244. if ((c->ssl_state.x509_cred_idx != x509_cred_idx) && (slot->refcnt <= 0)) {
  245. Log(LOG_INFO, "Discarding X509 certificate credentials from slot %zd.",
  246. c->ssl_state.x509_cred_idx);
  247. gnutls_certificate_free_keys(slot->x509_cred);
  248. gnutls_certificate_free_credentials(slot->x509_cred);
  249. slot->x509_cred = NULL;
  250. gnutls_dh_params_deinit(slot->dh_params);
  251. slot->dh_params = NULL;
  252. slot->refcnt = 0;
  253. }
  254. #endif
  255. assert(Conn_OPTION_ISSET(c, CONN_SSL));
  256. /* can't just set bitmask to 0 -- there are other, non-ssl related flags, e.g. CONN_ZIP. */
  257. Conn_OPTION_DEL(c, CONN_SSL_FLAGS_ALL);
  258. }
  259. bool
  260. ConnSSL_InitLibrary( void )
  261. {
  262. if (!Conf_SSLInUse()) {
  263. LogDebug("SSL not in use, skipping initialization.");
  264. return true;
  265. }
  266. #ifdef HAVE_LIBSSL
  267. SSL_CTX *newctx;
  268. #if OPENSSL_API_COMPAT < 0x10100000L
  269. if (!ssl_ctx) {
  270. SSL_library_init();
  271. SSL_load_error_strings();
  272. }
  273. #endif
  274. if (!RAND_status()) {
  275. Log(LOG_ERR, "OpenSSL PRNG not seeded: /dev/urandom missing?");
  276. /*
  277. * it is probably best to fail and let the user install EGD or
  278. * a similar program if no kernel random device is available.
  279. * According to OpenSSL RAND_egd(3): "The automatic query of
  280. * /var/run/egd-pool et al was added in OpenSSL 0.9.7";
  281. * so it makes little sense to deal with PRNGD seeding ourselves.
  282. */
  283. array_free(&Conf_SSLOptions.ListenPorts);
  284. return false;
  285. }
  286. newctx = SSL_CTX_new(SSLv23_method());
  287. if (!newctx) {
  288. LogOpenSSLError("Failed to create SSL context", NULL);
  289. array_free(&Conf_SSLOptions.ListenPorts);
  290. return false;
  291. }
  292. if (!ConnSSL_LoadServerKey_openssl(newctx)) {
  293. /* Failed to read new key but an old ssl context
  294. * already exists -> reuse old context */
  295. if (ssl_ctx) {
  296. SSL_CTX_free(newctx);
  297. Log(LOG_WARNING,
  298. "Re-Initializing of SSL failed, using old keys!");
  299. return true;
  300. }
  301. /* No preexisting old context -> error. */
  302. goto out;
  303. }
  304. if (SSL_CTX_set_cipher_list(newctx, Conf_SSLOptions.CipherList) == 0) {
  305. Log(LOG_ERR, "Failed to apply OpenSSL cipher list \"%s\"!",
  306. Conf_SSLOptions.CipherList);
  307. goto out;
  308. }
  309. SSL_CTX_set_session_id_context(newctx, (unsigned char *)"ngircd", 6);
  310. SSL_CTX_set_options(newctx, SSL_OP_SINGLE_DH_USE|SSL_OP_NO_SSLv2);
  311. SSL_CTX_set_mode(newctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
  312. SSL_CTX_set_verify(newctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
  313. Verify_openssl);
  314. SSL_CTX_free(ssl_ctx);
  315. ssl_ctx = newctx;
  316. Log(LOG_INFO, "%s initialized.", OpenSSL_version(OPENSSL_VERSION));
  317. return true;
  318. out:
  319. SSL_CTX_free(newctx);
  320. array_free(&Conf_SSLOptions.ListenPorts);
  321. return false;
  322. #endif
  323. #ifdef HAVE_LIBGNUTLS
  324. int err;
  325. static bool initialized;
  326. if (!initialized) {
  327. err = gnutls_global_init();
  328. if (err) {
  329. Log(LOG_ERR, "Failed to initialize GnuTLS: %s",
  330. gnutls_strerror(err));
  331. goto out;
  332. }
  333. }
  334. if (!ConnSSL_LoadServerKey_gnutls())
  335. goto out;
  336. if (priorities_cache != NULL) {
  337. gnutls_priority_deinit(priorities_cache);
  338. }
  339. if (gnutls_priority_init(&priorities_cache, Conf_SSLOptions.CipherList,
  340. NULL) != GNUTLS_E_SUCCESS) {
  341. Log(LOG_ERR,
  342. "Failed to apply GnuTLS cipher list \"%s\"!",
  343. Conf_SSLOptions.CipherList);
  344. goto out;
  345. }
  346. Log(LOG_INFO, "GnuTLS %s initialized.", gnutls_check_version(NULL));
  347. initialized = true;
  348. return true;
  349. out:
  350. array_free(&Conf_SSLOptions.ListenPorts);
  351. return false;
  352. #endif
  353. }
  354. #ifdef HAVE_LIBGNUTLS
  355. static bool
  356. ConnSSL_LoadServerKey_gnutls(void)
  357. {
  358. int err;
  359. const char *cert_file;
  360. x509_cred_slot *slot = NULL;
  361. gnutls_certificate_credentials_t x509_cred;
  362. err = gnutls_certificate_allocate_credentials(&x509_cred);
  363. if (err < 0) {
  364. Log(LOG_ERR, "Failed to allocate certificate credentials: %s",
  365. gnutls_strerror(err));
  366. return false;
  367. }
  368. cert_file = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile;
  369. if (!cert_file) {
  370. Log(LOG_ERR, "No SSL server key configured!");
  371. return false;
  372. }
  373. if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
  374. Log(LOG_WARNING,
  375. "Ignoring SSL \"KeyFilePassword\": Not supported by GnuTLS.");
  376. if (!Load_DH_params())
  377. return false;
  378. gnutls_certificate_set_dh_params(x509_cred, dh_params);
  379. err = gnutls_certificate_set_x509_key_file(x509_cred, cert_file, Conf_SSLOptions.KeyFile, GNUTLS_X509_FMT_PEM);
  380. if (err < 0) {
  381. Log(LOG_ERR,
  382. "Failed to set certificate key file (cert %s, key %s): %s",
  383. cert_file,
  384. Conf_SSLOptions.KeyFile ? Conf_SSLOptions.KeyFile : "(NULL)",
  385. gnutls_strerror(err));
  386. return false;
  387. }
  388. /* Free currently active x509 context (if any) unless it is still in use */
  389. slot = array_get(&x509_creds, sizeof(x509_cred_slot), x509_cred_idx);
  390. if ((slot != NULL) && (slot->refcnt <= 0) && (slot->x509_cred != NULL)) {
  391. Log(LOG_INFO, "Discarding X509 certificate credentials from slot %zd.", x509_cred_idx);
  392. gnutls_certificate_free_keys(slot->x509_cred);
  393. gnutls_certificate_free_credentials(slot->x509_cred);
  394. slot->x509_cred = NULL;
  395. gnutls_dh_params_deinit(slot->dh_params);
  396. slot->dh_params = NULL;
  397. slot->refcnt = 0;
  398. }
  399. /* Find free slot */
  400. x509_cred_idx = (size_t) -1;
  401. size_t i;
  402. for (slot = array_start(&x509_creds), i = 0;
  403. i < array_length(&x509_creds, sizeof(x509_cred_slot));
  404. slot++, i++) {
  405. if (slot->refcnt <= 0) {
  406. x509_cred_idx = i;
  407. break;
  408. }
  409. }
  410. /* ... allocate new slot otherwise. */
  411. if (x509_cred_idx == (size_t) -1) {
  412. x509_cred_idx = array_length(&x509_creds, sizeof(x509_cred_slot));
  413. slot = array_alloc(&x509_creds, sizeof(x509_cred_slot), x509_cred_idx);
  414. if (slot == NULL) {
  415. Log(LOG_ERR, "Failed to allocate new slot for certificate credentials");
  416. return false;
  417. }
  418. }
  419. Log(LOG_INFO, "Storing new X509 certificate credentials in slot %zd.", x509_cred_idx);
  420. slot->x509_cred = x509_cred;
  421. slot->refcnt = 0;
  422. return true;
  423. }
  424. #endif
  425. #ifdef HAVE_LIBSSL
  426. static bool
  427. ConnSSL_LoadServerKey_openssl(SSL_CTX *ctx)
  428. {
  429. char *cert_key;
  430. assert(ctx);
  431. if (!Conf_SSLOptions.KeyFile) {
  432. Log(LOG_ERR, "No SSL server key configured!");
  433. return false;
  434. }
  435. SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
  436. SSL_CTX_set_default_passwd_cb_userdata(ctx, &Conf_SSLOptions.KeyFilePassword);
  437. if (SSL_CTX_use_PrivateKey_file(ctx, Conf_SSLOptions.KeyFile, SSL_FILETYPE_PEM) != 1) {
  438. array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
  439. LogOpenSSLError("Failed to add private key", Conf_SSLOptions.KeyFile);
  440. return false;
  441. }
  442. cert_key = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile;
  443. if (SSL_CTX_use_certificate_chain_file(ctx, cert_key) != 1) {
  444. array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
  445. LogOpenSSLError("Failed to load certificate chain", cert_key);
  446. return false;
  447. }
  448. array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
  449. if (!SSL_CTX_check_private_key(ctx)) {
  450. LogOpenSSLError("Server private key does not match certificate", NULL);
  451. return false;
  452. }
  453. if (Load_DH_params()) {
  454. if (SSL_CTX_set_tmp_dh(ctx, dh_params) != 1)
  455. LogOpenSSLError("Error setting DH parameters", Conf_SSLOptions.DHFile);
  456. /* don't return false here: the non-DH modes will still work */
  457. DH_free(dh_params);
  458. dh_params = NULL;
  459. }
  460. return true;
  461. }
  462. #endif
  463. static bool
  464. ConnSSL_Init_SSL(CONNECTION *c)
  465. {
  466. int ret;
  467. LogDebug("Initializing SSL ...");
  468. assert(c != NULL);
  469. #ifdef HAVE_LIBSSL
  470. if (!ssl_ctx) {
  471. Log(LOG_ERR,
  472. "Can't initialize SSL context, OpenSSL initialization failed at startup!");
  473. return false;
  474. }
  475. assert(c->ssl_state.ssl == NULL);
  476. assert(c->ssl_state.fingerprint == NULL);
  477. c->ssl_state.ssl = SSL_new(ssl_ctx);
  478. if (!c->ssl_state.ssl) {
  479. LogOpenSSLError("Failed to create SSL structure", NULL);
  480. return false;
  481. }
  482. Conn_OPTION_ADD(c, CONN_SSL);
  483. ret = SSL_set_fd(c->ssl_state.ssl, c->sock);
  484. if (ret != 1) {
  485. LogOpenSSLError("Failed to set SSL file descriptor", NULL);
  486. ConnSSL_Free(c);
  487. return false;
  488. }
  489. #endif
  490. #ifdef HAVE_LIBGNUTLS
  491. Conn_OPTION_ADD(c, CONN_SSL);
  492. ret = gnutls_priority_set(c->ssl_state.gnutls_session, priorities_cache);
  493. if (ret != GNUTLS_E_SUCCESS) {
  494. Log(LOG_ERR, "Failed to set GnuTLS session priorities: %s",
  495. gnutls_strerror(ret));
  496. ConnSSL_Free(c);
  497. return false;
  498. }
  499. /*
  500. * The intermediate (long) cast is here to avoid a warning like:
  501. * "cast to pointer from integer of different size" on 64-bit platforms.
  502. * There doesn't seem to be an alternate GNUTLS API we could use instead, see e.g.
  503. * http://www.mail-archive.com/help-gnutls@gnu.org/msg00286.html
  504. */
  505. gnutls_transport_set_ptr(c->ssl_state.gnutls_session,
  506. (gnutls_transport_ptr_t) (long) c->sock);
  507. gnutls_certificate_server_set_request(c->ssl_state.gnutls_session,
  508. GNUTLS_CERT_REQUEST);
  509. Log(LOG_INFO, "Using X509 credentials from slot %zd", x509_cred_idx);
  510. c->ssl_state.x509_cred_idx = x509_cred_idx;
  511. x509_cred_slot *slot = array_get(&x509_creds, sizeof(x509_cred_slot), x509_cred_idx);
  512. slot->refcnt++;
  513. ret = gnutls_credentials_set(c->ssl_state.gnutls_session,
  514. GNUTLS_CRD_CERTIFICATE, slot->x509_cred);
  515. if (ret != 0) {
  516. Log(LOG_ERR, "Failed to set SSL credentials: %s",
  517. gnutls_strerror(ret));
  518. ConnSSL_Free(c);
  519. return false;
  520. }
  521. gnutls_dh_set_prime_bits(c->ssl_state.gnutls_session, DH_BITS_MIN);
  522. #endif
  523. return true;
  524. }
  525. bool
  526. ConnSSL_PrepareConnect(CONNECTION *c, UNUSED CONF_SERVER *s)
  527. {
  528. bool ret;
  529. #ifdef HAVE_LIBGNUTLS
  530. int err;
  531. err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_CLIENT);
  532. if (err) {
  533. Log(LOG_ERR, "Failed to initialize new SSL session: %s",
  534. gnutls_strerror(err));
  535. return false;
  536. }
  537. #endif
  538. ret = ConnSSL_Init_SSL(c);
  539. if (!ret)
  540. return false;
  541. Conn_OPTION_ADD(c, CONN_SSL_CONNECT);
  542. #ifdef HAVE_LIBSSL
  543. assert(c->ssl_state.ssl);
  544. SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_NONE, NULL);
  545. #endif
  546. return true;
  547. }
  548. /**
  549. * Check and handle error return codes after failed calls to SSL functions.
  550. *
  551. * OpenSSL:
  552. * SSL_connect(), SSL_accept(), SSL_do_handshake(), SSL_read(), SSL_peek(), or
  553. * SSL_write() on ssl.
  554. *
  555. * GnuTLS:
  556. * gnutlsssl_read(), gnutls_write() or gnutls_handshake().
  557. *
  558. * @param c The connection handle.
  559. * @prarm code The return code.
  560. * @param fname The name of the function in which the error occurred.
  561. * @return -1 on fatal errors, 0 if we can try again later.
  562. */
  563. static int
  564. ConnSSL_HandleError(CONNECTION * c, const int code, const char *fname)
  565. {
  566. #ifdef HAVE_LIBSSL
  567. int ret = SSL_ERROR_SYSCALL;
  568. unsigned long sslerr;
  569. int real_errno = errno;
  570. ret = SSL_get_error(c->ssl_state.ssl, code);
  571. switch (ret) {
  572. case SSL_ERROR_WANT_READ:
  573. io_event_del(c->sock, IO_WANTWRITE);
  574. Conn_OPTION_ADD(c, CONN_SSL_WANT_READ);
  575. return 0; /* try again later */
  576. case SSL_ERROR_WANT_WRITE:
  577. io_event_del(c->sock, IO_WANTREAD);
  578. Conn_OPTION_ADD(c, CONN_SSL_WANT_WRITE); /* fall through */
  579. case SSL_ERROR_NONE:
  580. return 0; /* try again later */
  581. case SSL_ERROR_ZERO_RETURN:
  582. LogDebug("SSL connection shut down normally.");
  583. break;
  584. case SSL_ERROR_SYSCALL:
  585. /* SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT,
  586. * and SSL_ERROR_WANT_X509_LOOKUP */
  587. sslerr = ERR_get_error();
  588. if (sslerr) {
  589. Log(LOG_ERR, "SSL error: %s [in %s()]!",
  590. ERR_error_string(sslerr, NULL), fname);
  591. } else {
  592. switch (code) { /* EOF that violated protocol */
  593. case 0:
  594. Log(LOG_ERR,
  595. "SSL error, client disconnected [in %s()]!",
  596. fname);
  597. break;
  598. case -1: /* low level socket I/O error, check errno */
  599. Log(LOG_ERR, "SSL error: %s [in %s()]!",
  600. strerror(real_errno), fname);
  601. }
  602. }
  603. break;
  604. case SSL_ERROR_SSL:
  605. LogOpenSSLError("SSL protocol error", fname);
  606. break;
  607. default:
  608. Log(LOG_ERR, "Unknown SSL error %d [in %s()]!", ret, fname);
  609. }
  610. ConnSSL_Free(c);
  611. return -1;
  612. #endif
  613. #ifdef HAVE_LIBGNUTLS
  614. switch (code) {
  615. case GNUTLS_E_AGAIN:
  616. case GNUTLS_E_INTERRUPTED:
  617. if (gnutls_record_get_direction(c->ssl_state.gnutls_session)) {
  618. Conn_OPTION_ADD(c, CONN_SSL_WANT_WRITE);
  619. io_event_del(c->sock, IO_WANTREAD);
  620. } else {
  621. Conn_OPTION_ADD(c, CONN_SSL_WANT_READ);
  622. io_event_del(c->sock, IO_WANTWRITE);
  623. }
  624. break;
  625. default:
  626. assert(code < 0);
  627. if (gnutls_error_is_fatal(code)) {
  628. Log(LOG_ERR, "SSL error: %s [%s].",
  629. gnutls_strerror(code), fname);
  630. ConnSSL_Free(c);
  631. return -1;
  632. }
  633. }
  634. return 0;
  635. #endif
  636. }
  637. static void
  638. ConnSSL_LogCertInfo( CONNECTION *c )
  639. {
  640. #ifdef HAVE_LIBSSL
  641. SSL *ssl = c->ssl_state.ssl;
  642. assert(ssl);
  643. Log(LOG_INFO, "Connection %d: initialized %s using cipher %s.",
  644. c->sock, SSL_get_version(ssl), SSL_get_cipher(ssl));
  645. #endif
  646. #ifdef HAVE_LIBGNUTLS
  647. gnutls_session_t sess = c->ssl_state.gnutls_session;
  648. gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess);
  649. Log(LOG_INFO, "Connection %d: initialized %s using cipher %s-%s.",
  650. c->sock,
  651. gnutls_protocol_get_name(gnutls_protocol_get_version(sess)),
  652. gnutls_cipher_get_name(cipher),
  653. gnutls_mac_get_name(gnutls_mac_get(sess)));
  654. #endif
  655. }
  656. /*
  657. Accept incoming SSL connection.
  658. Return Values:
  659. 1: SSL Connection established
  660. 0: try again
  661. -1: SSL Connection not established due to fatal error.
  662. */
  663. int
  664. ConnSSL_Accept( CONNECTION *c )
  665. {
  666. assert(c != NULL);
  667. if (!Conn_OPTION_ISSET(c, CONN_SSL)) {
  668. #ifdef HAVE_LIBGNUTLS
  669. int err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_SERVER);
  670. if (err) {
  671. Log(LOG_ERR, "Failed to initialize new SSL session: %s",
  672. gnutls_strerror(err));
  673. return false;
  674. }
  675. #endif
  676. if (!ConnSSL_Init_SSL(c))
  677. return -1;
  678. }
  679. return ConnectAccept(c, false );
  680. }
  681. int
  682. ConnSSL_Connect( CONNECTION *c )
  683. {
  684. assert(c != NULL);
  685. #ifdef HAVE_LIBSSL
  686. assert(c->ssl_state.ssl);
  687. #endif
  688. assert(Conn_OPTION_ISSET(c, CONN_SSL));
  689. return ConnectAccept(c, true);
  690. }
  691. static int
  692. ConnSSL_InitCertFp( CONNECTION *c )
  693. {
  694. const char hex[] = "0123456789abcdef";
  695. int i;
  696. #ifdef HAVE_LIBSSL
  697. unsigned char digest[EVP_MAX_MD_SIZE];
  698. unsigned int digest_size;
  699. X509 *cert;
  700. cert = SSL_get_peer_certificate(c->ssl_state.ssl);
  701. if (!cert)
  702. return 0;
  703. if (!X509_digest(cert, EVP_sha256(), digest, &digest_size)) {
  704. X509_free(cert);
  705. return 0;
  706. }
  707. X509_free(cert);
  708. #endif /* HAVE_LIBSSL */
  709. #ifdef HAVE_LIBGNUTLS
  710. gnutls_x509_crt_t cert;
  711. unsigned int cert_list_size;
  712. const gnutls_datum_t *cert_list;
  713. unsigned char digest[MAX_HASH_SIZE];
  714. size_t digest_size;
  715. if (gnutls_certificate_type_get(c->ssl_state.gnutls_session) !=
  716. GNUTLS_CRT_X509)
  717. return 0;
  718. if (gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS)
  719. return 0;
  720. cert_list_size = 0;
  721. cert_list = gnutls_certificate_get_peers(c->ssl_state.gnutls_session,
  722. &cert_list_size);
  723. if (!cert_list) {
  724. gnutls_x509_crt_deinit(cert);
  725. return 0;
  726. }
  727. if (gnutls_x509_crt_import(cert, &cert_list[0],
  728. GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
  729. gnutls_x509_crt_deinit(cert);
  730. return 0;
  731. }
  732. digest_size = sizeof(digest);
  733. if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, digest,
  734. &digest_size)) {
  735. gnutls_x509_crt_deinit(cert);
  736. return 0;
  737. }
  738. gnutls_x509_crt_deinit(cert);
  739. #endif /* HAVE_LIBGNUTLS */
  740. assert(c->ssl_state.fingerprint == NULL);
  741. c->ssl_state.fingerprint = malloc(SHA256_STRING_LEN);
  742. if (!c->ssl_state.fingerprint)
  743. return 0;
  744. for (i = 0; i < (int)digest_size; i++) {
  745. c->ssl_state.fingerprint[i * 2] = hex[digest[i] / 16];
  746. c->ssl_state.fingerprint[i * 2 + 1] = hex[digest[i] % 16];
  747. }
  748. c->ssl_state.fingerprint[i * 2] = '\0';
  749. return 1;
  750. }
  751. /* accept/connect wrapper. if connect is true, connect to peer, otherwise wait for incoming connection */
  752. static int
  753. ConnectAccept( CONNECTION *c, bool connect)
  754. {
  755. int ret;
  756. #ifdef HAVE_LIBSSL
  757. SSL *ssl = c->ssl_state.ssl;
  758. assert(ssl != NULL);
  759. ret = connect ? SSL_connect(ssl) : SSL_accept(ssl);
  760. if (1 != ret)
  761. return ConnSSL_HandleError(c, ret, connect ? "SSL_connect": "SSL_accept");
  762. #endif
  763. #ifdef HAVE_LIBGNUTLS
  764. (void) connect;
  765. ret = gnutls_handshake(c->ssl_state.gnutls_session);
  766. if (ret)
  767. return ConnSSL_HandleError(c, ret, "gnutls_handshake");
  768. #endif /* _GNUTLS */
  769. (void)ConnSSL_InitCertFp(c);
  770. Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT));
  771. ConnSSL_LogCertInfo(c);
  772. Conn_StartLogin(CONNECTION2ID(c));
  773. return 1;
  774. }
  775. ssize_t
  776. ConnSSL_Write(CONNECTION *c, const void *buf, size_t count)
  777. {
  778. ssize_t bw;
  779. Conn_OPTION_DEL(c, CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ);
  780. assert(count > 0);
  781. #ifdef HAVE_LIBSSL
  782. bw = (ssize_t) SSL_write(c->ssl_state.ssl, buf, count);
  783. #endif
  784. #ifdef HAVE_LIBGNUTLS
  785. bw = gnutls_write(c->ssl_state.gnutls_session, buf, count);
  786. #endif
  787. if (bw > 0)
  788. return bw;
  789. if (ConnSSL_HandleError( c, bw, "ConnSSL_Write") == 0)
  790. errno = EAGAIN; /* try again */
  791. return -1;
  792. }
  793. ssize_t
  794. ConnSSL_Read(CONNECTION *c, void * buf, size_t count)
  795. {
  796. ssize_t br;
  797. Conn_OPTION_DEL(c, CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ);
  798. #ifdef HAVE_LIBSSL
  799. br = (ssize_t) SSL_read(c->ssl_state.ssl, buf, count);
  800. if (br > 0) /* on EOF we have to call ConnSSL_HandleError(), see SSL_read(3) */
  801. return br;
  802. #endif
  803. #ifdef HAVE_LIBGNUTLS
  804. br = gnutls_read(c->ssl_state.gnutls_session, buf, count);
  805. if (br >= 0) /* on EOF we must _not_ call ConnSSL_HandleError, see gnutls_record_recv(3) */
  806. return br;
  807. #endif
  808. /* error on read: switch ConnSSL_HandleError() return values -> 0 is "try again", so return -1 and set EAGAIN */
  809. if (ConnSSL_HandleError(c, br, "ConnSSL_Read") == 0) {
  810. errno = EAGAIN;
  811. return -1;
  812. }
  813. return 0;
  814. }
  815. bool
  816. ConnSSL_GetCipherInfo(CONNECTION *c, char *buf, size_t len)
  817. {
  818. #ifdef HAVE_LIBSSL
  819. char *nl;
  820. SSL *ssl = c->ssl_state.ssl;
  821. if (!ssl)
  822. return false;
  823. *buf = 0;
  824. SSL_CIPHER_description(SSL_get_current_cipher(ssl), buf, len);
  825. nl = strchr(buf, '\n');
  826. if (nl)
  827. *nl = 0;
  828. return true;
  829. #endif
  830. #ifdef HAVE_LIBGNUTLS
  831. if (Conn_OPTION_ISSET(c, CONN_SSL)) {
  832. const char *name_cipher, *name_mac, *name_proto, *name_keyexchange;
  833. unsigned keysize;
  834. gnutls_session_t sess = c->ssl_state.gnutls_session;
  835. gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess);
  836. name_cipher = gnutls_cipher_get_name(cipher);
  837. name_mac = gnutls_mac_get_name(gnutls_mac_get(sess));
  838. keysize = gnutls_cipher_get_key_size(cipher) * 8;
  839. name_proto = gnutls_protocol_get_name(gnutls_protocol_get_version(sess));
  840. name_keyexchange = gnutls_kx_get_name(gnutls_kx_get(sess));
  841. return snprintf(buf, len, "%s-%s%15s Kx=%s Enc=%s(%u) Mac=%s",
  842. name_cipher, name_mac, name_proto, name_keyexchange, name_cipher, keysize, name_mac) > 0;
  843. }
  844. return false;
  845. #endif
  846. }
  847. char *
  848. ConnSSL_GetCertFp(CONNECTION *c)
  849. {
  850. return c->ssl_state.fingerprint;
  851. }
  852. bool
  853. ConnSSL_SetCertFp(CONNECTION *c, const char *fingerprint)
  854. {
  855. assert (c != NULL);
  856. c->ssl_state.fingerprint = strndup(fingerprint, SHA256_STRING_LEN - 1);
  857. return c->ssl_state.fingerprint != NULL;
  858. }
  859. #else
  860. bool
  861. ConnSSL_InitLibrary(void)
  862. {
  863. return true;
  864. }
  865. #endif /* SSL_SUPPORT */
  866. /* -eof- */