G_GNUC_COLD void tls_global_init(void) { static const struct { const char * const name; const int major; const int minor; } f = { "tls", 1, 0 }; char *cert_file, *key_file; #if !defined(REMAP_ZALLOC) && !defined(TRACK_MALLOC) && !defined(TRACK_ZALLOC) gnutls_global_set_mem_functions(halloc, halloc, NULL, hrealloc, hfree); #endif if (gnutls_global_init()) { g_error("gnutls_global_init() failed"); } #ifdef USE_TLS_CUSTOM_IO gnutls_global_set_log_level(9); gnutls_global_set_log_function(tls_log_function); #endif /* USE_TLS_CUSTOM_IO */ get_dh_params(); gnutls_certificate_allocate_credentials(&cert_cred); key_file = make_pathname(settings_config_dir(), "key.pem"); cert_file = make_pathname(settings_config_dir(), "cert.pem"); if (file_exists(key_file) && file_exists(cert_file)) { int ret; ret = gnutls_certificate_set_x509_key_file(cert_cred, cert_file, key_file, GNUTLS_X509_FMT_PEM); if (ret < 0) { g_warning("gnutls_certificate_set_x509_key_file() failed: %s", gnutls_strerror(ret)); } else { gnutls_certificate_set_dh_params(cert_cred, get_dh_params()); } } HFREE_NULL(key_file); HFREE_NULL(cert_file); header_features_add(FEATURES_CONNECTIONS, f.name, f.major, f.minor); header_features_add(FEATURES_G2_CONNECTIONS, f.name, f.major, f.minor); header_features_add(FEATURES_DOWNLOADS, f.name, f.major, f.minor); header_features_add(FEATURES_UPLOADS, f.name, f.major, f.minor); }
DH * usmDHGetUserDHptr(struct usmUser *user, int for_auth_key) { DH *dh, *dh_params; void **theptr; if (user == NULL) return NULL; if (for_auth_key == 1) theptr = &user->usmDHUserAuthKeyChange; else theptr = &user->usmDHUserPrivKeyChange; if (!*theptr) { /* * copy the system parameters to the local ones */ dh = DH_new(); if (!dh) return NULL; dh_params = get_dh_params(); if (!dh_params) return NULL; dh->g = BN_dup(dh_params->g); dh->p = BN_dup(dh_params->p); if (!dh->g || !dh->p) return NULL; DH_generate_key(dh); *theptr = dh; } else { dh = (DH *) * theptr; } return dh; }
/** * Initiates a new TLS session. * * @return 0 on success, -1 on error. */ int tls_init(struct gnutella_socket *s) { /** * ANON-DH is enabled because we don't use PKI. * DEFLATE is disabled because it seems to cause crashes. * ARCFOUR-40 is disabled because it is deprecated. */ static const char prio_want[] = "NORMAL:+ANON-DH:-ARCFOUR-40:-COMP-DEFLATE"; /* "-COMP-DEFLATE" is causing an error on MinGW with GnuTLS 2.10.2 */ static const char prio_must[] = "NORMAL:+ANON-DH:-ARCFOUR-40"; const bool server = SOCK_CONN_INCOMING == s->direction; struct tls_context *ctx; const char *fn; int e; #define TRY(function) (fn = (#function)), e = function socket_check(s); WALLOC0(ctx); ctx->s = s; s->tls.ctx = ctx; if ( TRY(gnutls_init)(&ctx->session, server ? GNUTLS_SERVER : GNUTLS_CLIENT) ) { ctx->session = NULL; goto failure; } if (TRY(gnutls_priority_set_direct)(ctx->session, prio_want, NULL)) { const char *error; if (TRY(gnutls_priority_set_direct)(ctx->session, prio_must, &error)) { g_warning("%s() failed at \"%s\"", fn, error); goto failure; } } if (TRY(gnutls_credentials_set)(ctx->session, GNUTLS_CRD_CERTIFICATE, cert_cred)) goto failure; gnutls_dh_set_prime_bits(ctx->session, TLS_DH_BITS); #ifdef USE_TLS_CUSTOM_IO gnutls_transport_set_ptr(ctx->session, s); gnutls_transport_set_push_function(ctx->session, tls_push); gnutls_transport_set_pull_function(ctx->session, tls_pull); #if !HAS_TLS(2, 12) /* * This routine has been removed starting TLS 3.0. It was used to disable * the lowat feature, and apparently this is now always the case in recent * TLS versions. --RAM, 2011-09-28 * * It's also flagged as deprecated in 2.12.x, so don't use it there. * --RAM, 2011-12-15 */ gnutls_transport_set_lowat(ctx->session, 0); #endif #else /* !USE_TLS_CUSTOM_IO */ g_assert(is_valid_fd(s->file_desc)); gnutls_transport_set_ptr(ctx->session, int_to_pointer(s->file_desc)); #endif /* USE_TLS_CUSTOM_IO */ if (server) { if (TRY(gnutls_anon_allocate_server_credentials)(&ctx->server_cred)) goto failure; gnutls_anon_set_server_dh_params(ctx->server_cred, get_dh_params()); if (TRY(gnutls_credentials_set)(ctx->session, GNUTLS_CRD_ANON, ctx->server_cred)) goto failure; } else { if (TRY(gnutls_anon_allocate_client_credentials)(&ctx->client_cred)) goto failure; if (TRY(gnutls_credentials_set)(ctx->session, GNUTLS_CRD_ANON, ctx->client_cred)) goto failure; } return 0; failure: g_warning("%s() failed: %s", EMPTY_STRING(fn), gnutls_strerror(e)); tls_free(s); return -1; #undef TRY }