static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd) { gnutls_session_t dtls_ssl; gnutls_datum_t master_secret, session_id; int err; int cipher; for (cipher = 0; cipher < sizeof(gnutls_dtls_ciphers)/sizeof(gnutls_dtls_ciphers[0]); cipher++) { if (!strcmp(vpninfo->dtls_cipher, gnutls_dtls_ciphers[cipher].name)) goto found_cipher; } vpn_progress(vpninfo, PRG_ERR, _("Unknown DTLS parameters for requested CipherSuite '%s'\n"), vpninfo->dtls_cipher); vpninfo->dtls_attempt_period = 0; return -EINVAL; found_cipher: gnutls_init(&dtls_ssl, GNUTLS_CLIENT|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK); err = gnutls_priority_set_direct(dtls_ssl, gnutls_dtls_ciphers[cipher].prio, NULL); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Failed to set DTLS priority: %s\n"), gnutls_strerror(err)); gnutls_deinit(dtls_ssl); vpninfo->dtls_attempt_period = 0; return -EINVAL; } gnutls_transport_set_ptr(dtls_ssl, (gnutls_transport_ptr_t)(intptr_t)dtls_fd); gnutls_record_disable_padding(dtls_ssl); master_secret.data = vpninfo->dtls_secret; master_secret.size = sizeof(vpninfo->dtls_secret); session_id.data = vpninfo->dtls_session_id; session_id.size = sizeof(vpninfo->dtls_session_id); err = gnutls_session_set_premaster(dtls_ssl, GNUTLS_CLIENT, gnutls_dtls_ciphers[cipher].version, GNUTLS_KX_RSA, gnutls_dtls_ciphers[cipher].cipher, gnutls_dtls_ciphers[cipher].mac, GNUTLS_COMP_NULL, &master_secret, &session_id); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Failed to set DTLS session parameters: %s\n"), gnutls_strerror(err)); gnutls_deinit(dtls_ssl); vpninfo->dtls_attempt_period = 0; return -EINVAL; } vpninfo->dtls_ssl = dtls_ssl; return 0; }
static struct mailstream_ssl_data * ssl_data_new(int fd, time_t timeout, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) { struct mailstream_ssl_data * ssl_data; gnutls_session session; struct mailstream_cancel * cancel; gnutls_certificate_credentials_t xcred; int r; struct mailstream_ssl_context * ssl_context = NULL; mailstream_ssl_init(); if (gnutls_certificate_allocate_credentials (&xcred) != 0) return NULL; r = gnutls_init(&session, GNUTLS_CLIENT); if (session == NULL || r != 0) return NULL; if (callback != NULL) { ssl_context = mailstream_ssl_context_new(session, fd); callback(ssl_context, cb_data); } gnutls_session_set_ptr(session, ssl_context); gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); gnutls_certificate_client_set_retrieve_function(xcred, mailstream_gnutls_client_cert_cb); gnutls_set_default_priority(session); gnutls_priority_set_direct(session, "NORMAL", NULL); gnutls_record_disable_padding(session); gnutls_dh_set_prime_bits(session, 512); gnutls_transport_set_ptr(session, (gnutls_transport_ptr) fd); /* lower limits on server key length restriction */ gnutls_dh_set_prime_bits(session, 512); if (timeout == 0) { timeout_value = mailstream_network_delay.tv_sec * 1000 + timeout.tv_usec / 1000; } else { timeout_value = timeout; } gnutls_handshake_set_timeout(session, timeout_value); do { r = gnutls_handshake(session); } while (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED); if (r < 0) { gnutls_perror(r); goto free_ssl_conn; } cancel = mailstream_cancel_new(); if (cancel == NULL) goto free_ssl_conn; r = mailstream_prepare_fd(fd); if (r < 0) goto free_cancel; ssl_data = malloc(sizeof(* ssl_data)); if (ssl_data == NULL) goto err; ssl_data->fd = fd; ssl_data->session = session; ssl_data->xcred = xcred; ssl_data->cancel = cancel; mailstream_ssl_context_free(ssl_context); return ssl_data; free_cancel: mailstream_cancel_free(cancel); free_ssl_conn: gnutls_certificate_free_credentials(xcred); mailstream_ssl_context_free(ssl_context); gnutls_deinit(session); err: return NULL; }
TDSRET tds_ssl_init(TDSSOCKET *tds) { gnutls_session_t session; gnutls_certificate_credentials_t xcred; int ret; const char *tls_msg; xcred = NULL; session = NULL; tls_msg = "initializing tls"; if (!tls_initialized) { ret = 0; tds_mutex_lock(&tls_mutex); if (!tls_initialized) { tds_gcry_init(); ret = gnutls_global_init(); if (ret == 0) tls_initialized = 1; } tds_mutex_unlock(&tls_mutex); if (ret != 0) goto cleanup; } if (tds_write_dump && tls_initialized < 2) { gnutls_global_set_log_level(11); gnutls_global_set_log_function(tds_tls_log); tls_initialized = 2; } tls_msg = "allocating credentials"; ret = gnutls_certificate_allocate_credentials(&xcred); if (ret != 0) goto cleanup; if (!tds_dstr_isempty(&tds->login->cafile)) { tls_msg = "loading CA file"; if (strcasecmp(tds_dstr_cstr(&tds->login->cafile), "system") == 0) ret = gnutls_certificate_set_x509_system_trust(xcred); else ret = gnutls_certificate_set_x509_trust_file(xcred, tds_dstr_cstr(&tds->login->cafile), GNUTLS_X509_FMT_PEM); if (ret <= 0) goto cleanup; if (!tds_dstr_isempty(&tds->login->crlfile)) { tls_msg = "loading CRL file"; ret = gnutls_certificate_set_x509_crl_file(xcred, tds_dstr_cstr(&tds->login->crlfile), GNUTLS_X509_FMT_PEM); if (ret <= 0) goto cleanup; } #ifdef HAVE_GNUTLS_CERTIFICATE_SET_VERIFY_FUNCTION gnutls_certificate_set_verify_function(xcred, tds_verify_certificate); #endif } /* Initialize TLS session */ tls_msg = "initializing session"; ret = gnutls_init(&session, GNUTLS_CLIENT); if (ret != 0) goto cleanup; gnutls_transport_set_ptr(session, tds); gnutls_transport_set_pull_function(session, tds_pull_func_login); gnutls_transport_set_push_function(session, tds_push_func_login); /* NOTE: there functions return int however they cannot fail */ /* use default priorities... */ gnutls_set_default_priority(session); /* ... but overwrite some */ ret = gnutls_priority_set_direct (session, "NORMAL:%COMPAT:-VERS-SSL3.0", NULL); if (ret != 0) goto cleanup; /* mssql does not like padding too much */ #ifdef HAVE_GNUTLS_RECORD_DISABLE_PADDING gnutls_record_disable_padding(session); #endif /* put the anonymous credentials to the current session */ tls_msg = "setting credential"; ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); if (ret != 0) goto cleanup; /* Perform the TLS handshake */ tls_msg = "handshake"; ret = gnutls_handshake (session); if (ret != 0) goto cleanup; #ifndef HAVE_GNUTLS_CERTIFICATE_SET_VERIFY_FUNCTION ret = tds_verify_certificate(session); if (ret != 0) goto cleanup; #endif tdsdump_log(TDS_DBG_INFO1, "handshake succeeded!!\n"); gnutls_transport_set_ptr(session, tds->conn); gnutls_transport_set_pull_function(session, tds_pull_func); gnutls_transport_set_push_function(session, tds_push_func); tds->conn->tls_session = session; tds->conn->tls_credentials = xcred; return TDS_SUCCESS; cleanup: if (session) gnutls_deinit(session); if (xcred) gnutls_certificate_free_credentials(xcred); tdsdump_log(TDS_DBG_ERROR, "%s failed: %s\n", tls_msg, gnutls_strerror (ret)); return TDS_FAIL; }
int tls_connection_enable_workaround(void *ssl_ctx, struct tls_connection *conn) { gnutls_record_disable_padding(conn->session); return 0; }
static struct mailstream_ssl_data * ssl_data_new(int fd, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) { struct mailstream_ssl_data * ssl_data; gnutls_session session; struct mailstream_cancel * cancel; const int cipher_prio[] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_ARCFOUR_128, 0 }; const int kx_prio[] = { GNUTLS_KX_DHE_RSA, GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS, 0 }; const int mac_prio[] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 }; const int proto_prio[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 }; gnutls_certificate_credentials_t xcred; int r; struct mailstream_ssl_context * ssl_context = NULL; mailstream_ssl_init(); if (gnutls_certificate_allocate_credentials (&xcred) != 0) return NULL; r = gnutls_init(&session, GNUTLS_CLIENT); if (session == NULL || r != 0) return NULL; if (callback != NULL) { ssl_context = mailstream_ssl_context_new(session, fd); callback(ssl_context, cb_data); } gnutls_session_set_ptr(session, ssl_context); gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); gnutls_certificate_client_set_retrieve_function(xcred, mailstream_gnutls_client_cert_cb); gnutls_set_default_priority(session); gnutls_protocol_set_priority (session, proto_prio); gnutls_cipher_set_priority (session, cipher_prio); gnutls_kx_set_priority (session, kx_prio); gnutls_mac_set_priority (session, mac_prio); gnutls_record_disable_padding(session); gnutls_dh_set_prime_bits(session, 512); gnutls_transport_set_ptr(session, (gnutls_transport_ptr) fd); /* lower limits on server key length restriction */ gnutls_dh_set_prime_bits(session, 512); do { r = gnutls_handshake(session); } while (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED); if (r < 0) { gnutls_perror(r); goto free_ssl_conn; } cancel = mailstream_cancel_new(); if (cancel == NULL) goto free_ssl_conn; r = mailstream_prepare_fd(fd); if (r < 0) goto free_cancel; ssl_data = malloc(sizeof(* ssl_data)); if (ssl_data == NULL) goto err; ssl_data->fd = fd; ssl_data->session = session; ssl_data->xcred = xcred; ssl_data->cancel = cancel; mailstream_ssl_context_free(ssl_context); return ssl_data; free_cancel: mailstream_cancel_free(cancel); free_ssl_conn: gnutls_certificate_free_credentials(xcred); mailstream_ssl_context_free(ssl_context); gnutls_deinit(session); err: return NULL; }