static gnutls_session_t initialize_tls_session (struct params_res *params) { gnutls_session_t session; gnutls_init (&session, GNUTLS_SERVER); /* avoid calling all the priority functions, since the defaults * are adequate. */ gnutls_priority_set_direct (session, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL); gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); gnutls_dh_set_prime_bits (session, DH_BITS); if (params->enable_db) { gnutls_db_set_retrieve_function (session, wrap_db_fetch); gnutls_db_set_remove_function (session, wrap_db_delete); gnutls_db_set_store_function (session, wrap_db_store); gnutls_db_set_ptr (session, NULL); } if (params->enable_session_ticket_server) gnutls_session_ticket_enable_server (session, &session_ticket_key); return session; }
static gnutls_session_t initialize_tls_session (struct params_res *params) { gnutls_session_t session; const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; gnutls_init (&session, GNUTLS_SERVER); /* avoid calling all the priority functions, since the defaults * are adequate. */ gnutls_set_default_priority (session); gnutls_kx_set_priority (session, kx_prio); gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); gnutls_dh_set_prime_bits (session, DH_BITS); if (params->enable_db) { gnutls_db_set_retrieve_function (session, wrap_db_fetch); gnutls_db_set_remove_function (session, wrap_db_delete); gnutls_db_set_store_function (session, wrap_db_store); gnutls_db_set_ptr (session, NULL); } #ifdef ENABLE_SESSION_TICKET if (params->enable_session_ticket_server) gnutls_session_ticket_enable_server (session, &session_ticket_key); #endif return session; }
static void server(int sds[], struct params_res *params) { gnutls_anon_server_credentials_t anoncred; static gnutls_datum_t session_ticket_key = { NULL, 0 }; int ret; size_t t; gnutls_session_t session; /* this must be called once in the program, it is mostly for the server. */ if (debug) { gnutls_global_set_log_function(tls_log_func); gnutls_global_set_log_level(3); } global_init(); gnutls_anon_allocate_server_credentials(&anoncred); if (debug) success("Launched, generating DH parameters...\n"); gnutls_anon_set_server_dh_params(anoncred, dh_params); if (params->enable_db) { wrap_db_init(); } if (params->enable_session_ticket_server) gnutls_session_ticket_key_generate(&session_ticket_key); for (t = 0; t < SESSIONS; t++) { int sd = sds[t]; gnutls_init(&session, GNUTLS_SERVER | GNUTLS_DATAGRAM); gnutls_priority_set_direct(session, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL); gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred); gnutls_dh_set_prime_bits(session, DH_BITS); if (params->enable_db) { gnutls_db_set_retrieve_function(session, wrap_db_fetch); gnutls_db_set_remove_function(session, wrap_db_delete); gnutls_db_set_store_function(session, wrap_db_store); gnutls_db_set_ptr(session, NULL); } if (params->enable_session_ticket_server) gnutls_session_ticket_enable_server(session, &session_ticket_key); gnutls_transport_set_int(session, sd); gnutls_dtls_set_timeouts(session, 3*1000, 240 * 1000); do { ret = gnutls_handshake(session); } while (ret < 0 && (ret == GNUTLS_E_INTERRUPTED||ret == GNUTLS_E_AGAIN)); if (ret < 0) { close(sd); gnutls_deinit(session); kill(child, SIGTERM); fail("server: Handshake has failed (%s)\n\n", gnutls_strerror(ret)); return; } if (debug) success("server: Handshake was completed\n"); /* see the Getting peer's information example */ /* print_info(session); */ for (;;) { memset(buffer, 0, MAX_BUF + 1); ret = gnutls_record_recv(session, buffer, MAX_BUF); if (ret == 0) { if (debug) success ("server: Peer has closed the GnuTLS connection\n"); break; } else if (ret < 0) { kill(child, SIGTERM); fail("server: Received corrupted data(%d). Closing...\n", ret); break; } else if (ret > 0) { /* echo data back to the client */ gnutls_record_send(session, buffer, strlen(buffer)); } } /* do not wait for the peer to close the connection. */ gnutls_bye(session, GNUTLS_SHUT_WR); close(sd); gnutls_deinit(session); } if (params->enable_db) { wrap_db_deinit(); } gnutls_free(session_ticket_key.data); session_ticket_key.data = NULL; gnutls_anon_free_server_credentials(anoncred); if (debug) success("server: finished\n"); }
static Ecore_Con_Ssl_Error _ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl) { const gnutls_datum_t *cert_list; unsigned int iter, cert_list_size; const char *priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0"; int ret = 0; switch (cl->ssl_state) { case ECORE_CON_SSL_STATE_DONE: return ECORE_CON_SSL_ERROR_NONE; case ECORE_CON_SSL_STATE_INIT: if (cl->host_server->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */ return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; switch (cl->host_server->type & ECORE_CON_SSL) { case ECORE_CON_USE_SSL3: case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-TLS1.0:!VERS-TLS1.1"; break; case ECORE_CON_USE_TLS: case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-SSL3.0"; break; case ECORE_CON_USE_MIXED: case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: break; default: return ECORE_CON_SSL_ERROR_NONE; } _client_connected++; SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&cl->session, GNUTLS_SERVER)); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_key_generate(&cl->session_ticket)); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_server(cl->session, &cl->session_ticket)); INF("Applying priority string: %s", priority); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(cl->session, priority, NULL)); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_CERTIFICATE, cl->host_server->cert)); // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_PSK, cl->host_server->pskcred_s)); if (!cl->host_server->use_cert) SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_ANON, cl->host_server->anoncred_s)); gnutls_certificate_server_set_request(cl->session, GNUTLS_CERT_REQUEST); gnutls_dh_set_prime_bits(cl->session, 2048); gnutls_transport_set_ptr(cl->session, (gnutls_transport_ptr_t)((intptr_t)cl->fd)); cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; case ECORE_CON_SSL_STATE_HANDSHAKING: if (!cl->session) { DBG("Client was previously lost, going to error condition"); goto error; } DBG("calling gnutls_handshake()"); ret = gnutls_handshake(cl->session); SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret)); if (!ret) { cl->handshaking = EINA_FALSE; cl->ssl_state = ECORE_CON_SSL_STATE_DONE; } else { if (gnutls_record_get_direction(cl->session)) ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); else ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); return ECORE_CON_SSL_ERROR_NONE; } default: break; } if (!cl->host_server->verify) /* not verifying certificates, so we're done! */ return ECORE_CON_SSL_ERROR_NONE; ret = 0; /* use CRL/CA lists to verify */ SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(cl->session, &iter)); if (iter & GNUTLS_CERT_INVALID) ERR("The certificate is not trusted."); else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND) ERR("The certificate hasn't got a known issuer."); else if (iter & GNUTLS_CERT_REVOKED) ERR("The certificate has been revoked."); else if (iter & GNUTLS_CERT_EXPIRED) ERR("The certificate has expired"); else if (iter & GNUTLS_CERT_NOT_ACTIVATED) ERR("The certificate is not yet activated"); if (iter) goto error; if (gnutls_certificate_type_get(cl->session) != GNUTLS_CRT_X509) { ERR("Warning: PGP certificates are not yet supported!"); goto error; } SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(cl->session, &cert_list_size))); SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size); DBG("SSL certificate verification succeeded!"); return ECORE_CON_SSL_ERROR_NONE; error: _gnutls_print_errors(ret); if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)) ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(cl->session))); if (cl->session && (cl->ssl_state != ECORE_CON_SSL_STATE_DONE)) { ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(cl->session))); ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(cl->session))); } _ecore_con_ssl_client_shutdown_gnutls(cl); return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; }
static gboolean mod_gnutls_con_new(liConnection *con, int fd) { liEventLoop *loop = &con->wrk->loop; liServer *srv = con->srv; mod_context *ctx = con->srv_sock->data; mod_connection_ctx *conctx; gnutls_session_t session; int r; if (GNUTLS_E_SUCCESS > (r = gnutls_init(&session, GNUTLS_SERVER))) { ERROR(srv, "gnutls_init (%s): %s", gnutls_strerror_name(r), gnutls_strerror(r)); return FALSE; } mod_gnutls_context_acquire(ctx); if (GNUTLS_E_SUCCESS > (r = gnutls_priority_set(session, ctx->server_priority))) { ERROR(srv, "gnutls_priority_set (%s): %s", gnutls_strerror_name(r), gnutls_strerror(r)); goto fail; } if (GNUTLS_E_SUCCESS > (r = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, ctx->server_cert))) { ERROR(srv, "gnutls_credentials_set (%s): %s", gnutls_strerror_name(r), gnutls_strerror(r)); goto fail; } if (NULL != ctx->session_db) { gnutls_db_set_ptr(session, ctx->session_db); gnutls_db_set_remove_function(session, session_db_remove_cb); gnutls_db_set_retrieve_function(session, session_db_retrieve_cb); gnutls_db_set_store_function(session, session_db_store_cb); } #ifdef HAVE_SESSION_TICKET if (GNUTLS_E_SUCCESS > (r = gnutls_session_ticket_enable_server(session, &ctx->ticket_key))) { ERROR(srv, "gnutls_session_ticket_enable_server (%s): %s", gnutls_strerror_name(r), gnutls_strerror(r)); goto fail; } #endif #ifdef GNUTLS_ALPN_MAND { static const gnutls_datum_t proto_http1 = { (unsigned char*) CONST_STR_LEN("http/1.1") }; gnutls_alpn_set_protocols(session, &proto_http1, 1, 0); } #endif conctx = g_slice_new0(mod_connection_ctx); conctx->session = session; conctx->sock_stream = li_iostream_new(con->wrk, fd, tcp_io_cb, conctx); conctx->client_hello_stream = li_ssl_client_hello_stream(&con->wrk->loop, gnutls_client_hello_cb, conctx); #ifdef USE_SNI li_job_init(&conctx->sni_job, sni_job_cb); conctx->sni_jobref = li_job_ref(&con->wrk->loop.jobqueue, &conctx->sni_job); #endif li_stream_connect(&conctx->sock_stream->stream_in, conctx->client_hello_stream); conctx->tls_filter = li_gnutls_filter_new(srv, con->wrk, &filter_callbacks, conctx, conctx->session, conctx->client_hello_stream, &conctx->sock_stream->stream_out); conctx->con = con; conctx->ctx = ctx; con->con_sock.data = conctx; con->con_sock.callbacks = &gnutls_tcp_cbs; con->con_sock.raw_out = li_stream_plug_new(loop); con->con_sock.raw_in = li_stream_plug_new(loop); con->info.is_ssl = TRUE; return TRUE; fail: gnutls_deinit(session); mod_gnutls_context_release(ctx); return FALSE; }
/* Returns true if resumed */ static unsigned handshake(const char *prio, unsigned t, const gnutls_datum_t *sdata, gnutls_datum_t *ndata, gnutls_datum_t *skey, struct hsk_st *h) { int ret; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; char buf[128]; gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(6); assert(gnutls_certificate_allocate_credentials(&serverx509cred)>=0); assert(gnutls_certificate_set_x509_key_mem(serverx509cred, &server_cert, &server_key, GNUTLS_X509_FMT_PEM)>=0); assert(gnutls_init(&server, GNUTLS_SERVER)>=0); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); assert(gnutls_priority_set_direct(server, prio, NULL)>=0); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); gnutls_session_set_ptr(server, h); gnutls_db_set_cache_expiration(server, t); assert(gnutls_session_ticket_enable_server(server, skey) >= 0); gnutls_handshake_set_hook_function(server, -1, GNUTLS_HOOK_POST, handshake_callback); assert(gnutls_certificate_allocate_credentials(&clientx509cred)>=0); assert(gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM)>=0); assert(gnutls_init(&client, GNUTLS_CLIENT)>=0); assert(gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred)>=0); assert(gnutls_priority_set_direct(client, prio, NULL)>=0); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); if (sdata) { assert(gnutls_session_set_data(client, sdata->data, sdata->size)>=0); } memset(buf, 0, sizeof(buf)); ret = gnutls_session_set_data(client, buf, sizeof(buf)); if (ret != GNUTLS_E_DB_ERROR) { fail("unexpected error: %s\n", gnutls_strerror(ret)); } HANDSHAKE(client, server); gnutls_record_recv(client, buf, sizeof(buf)); if (ndata) { ret = gnutls_session_get_data2(client, ndata); if (ret < 0) { fail("unexpected error: %s\n", gnutls_strerror(ret)); } } ret = gnutls_session_is_resumed(client); gnutls_deinit(server); gnutls_deinit(client); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); reset_buffers(); return ret; }
static void server(int fd, const char *prio) { int ret; char buffer[MAX_BUF + 1]; gnutls_session_t session; gnutls_certificate_credentials_t x509_cred; gnutls_datum_t skey; /* this must be called once in the program */ global_init(); memset(buffer, 0, sizeof(buffer)); if (debug) { gnutls_global_set_log_function(server_log_func); gnutls_global_set_log_level(4711); } assert(gnutls_certificate_allocate_credentials(&x509_cred)>=0); assert(gnutls_certificate_set_x509_key_mem(x509_cred, &server_cert, &server_key, GNUTLS_X509_FMT_PEM)>=0); assert(gnutls_init(&session, GNUTLS_SERVER)>=0); assert(gnutls_session_ticket_key_generate(&skey)>=0); assert(gnutls_session_ticket_enable_server(session, &skey) >= 0); gnutls_handshake_set_hook_function(session, GNUTLS_HANDSHAKE_NEW_SESSION_TICKET, GNUTLS_HOOK_POST, handshake_callback); /* avoid calling all the priority functions, since the defaults * are adequate. */ assert(gnutls_priority_set_direct(session, prio, NULL)>=0); gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); gnutls_transport_set_int(session, fd); do { ret = gnutls_handshake(session); } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); if (ret < 0) { /* failure is expected here */ goto end; } if (debug) { success("server: Handshake was completed\n"); } if (debug) success("server: TLS version is: %s\n", gnutls_protocol_get_name (gnutls_protocol_get_version(session))); if (sent == 0) { fail("client: didn't send new sessiont ticket\n"); terminate(); } /* do not wait for the peer to close the connection. */ gnutls_bye(session, GNUTLS_SHUT_WR); end: close(fd); gnutls_deinit(session); gnutls_free(skey.data); gnutls_certificate_free_credentials(x509_cred); gnutls_global_deinit(); if (debug) success("server: finished\n"); }