Exemple #1
0
int dtls_try_handshake(struct openconnect_info *vpninfo)
{
	int err = gnutls_handshake(vpninfo->dtls_ssl);

	if (!err) {
#ifdef HAVE_GNUTLS_DTLS_SET_DATA_MTU
		/* Make sure GnuTLS's idea of the MTU is sufficient to take
		   a full VPN MTU (with 1-byte header) in a data record. */
		err = gnutls_dtls_set_data_mtu(vpninfo->dtls_ssl, vpninfo->ip_info.mtu + 1);
		if (err) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Failed to set DTLS MTU: %s\n"),
				     gnutls_strerror(err));
			goto error;
		}
#else
		/* If we don't have gnutls_dtls_set_data_mtu() then make sure
		   we leave enough headroom by adding the worst-case overhead.
		   We only support AES128-CBC and DES-CBC3-SHA anyway, so
		   working out the worst case isn't hard. */
		gnutls_dtls_set_mtu(vpninfo->dtls_ssl,
				    vpninfo->ip_info.mtu + 1 /* packet + header */
				    + 13 /* DTLS header */
				    + 20 /* biggest supported MAC (SHA1) */
				    + 16 /* biggest supported IV (AES-128) */
				    + 16 /* max padding */);
#endif

		vpninfo->dtls_state = DTLS_CONNECTED;
		vpn_progress(vpninfo, PRG_INFO,
			     _("Established DTLS connection (using GnuTLS). Ciphersuite %s.\n"),
			     vpninfo->dtls_cipher);

		vpninfo->dtls_times.last_rekey = vpninfo->dtls_times.last_rx = 
			vpninfo->dtls_times.last_tx = time(NULL);

		/* XXX: For OpenSSL we explicitly prevent retransmits here. */
		return 0;
	}

	if (err == GNUTLS_E_AGAIN) {
		if (time(NULL) < vpninfo->new_dtls_started + 12)
			return 0;
		vpn_progress(vpninfo, PRG_DEBUG, _("DTLS handshake timed out\n"));
	}

	vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %s\n"),
		     gnutls_strerror(err));

 error:
	dtls_close(vpninfo);

	vpninfo->dtls_state = DTLS_SLEEPING;
	time(&vpninfo->new_dtls_started);
	return -EINVAL;
}
Exemple #2
0
struct dtls_gnutls_data *dtls_gnutls_data_create(struct conn *conn,int config)
{
	const char *errpos;
	int rc;
	gnutls_datum_t key;
	int bits;
	struct dtls_gnutls_data *d = malloc(sizeof(struct dtls_gnutls_data));
	if (!d)
		return 0;

	gnutls_global_set_log_level(10);
	gnutls_global_set_log_function(dtls_log_cb);
	
	rc = gnutls_init(&d->session, config); 
	if (rc < 0) {
		cw_log(LOG_ERR, "DTLS - Can't init session: %s", gnutls_strerror(rc));
		dtls_gnutls_data_destroy(d);
		return 0;
	}


	gnutls_certificate_allocate_credentials(&d->x509_cred);




	/* Set credentials */

	if (conn->dtls_cert_file && conn->dtls_key_file){

		rc = gnutls_certificate_set_x509_key_file(d->x509_cred, conn->dtls_cert_file,
							  conn->dtls_key_file, GNUTLS_X509_FMT_PEM);

		if (rc < 0) {
			cw_log(LOG_ERR, "DTLS - Can't set cert/key: %s", gnutls_strerror(rc));
			dtls_gnutls_data_destroy(d);
			return 0;
		}
	}



/*
#if GNUTLS_VERSION_NUMBER >= 0x030100
	bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_INSECURE);
#else
*/	bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY);
/*#endif*/






	/* Set ciphers */
/*
	rc = gnutls_priority_init(&d->priority_cache, conn->dtls_cipher, &errpos);
	if (rc < 0) {
		cw_log(LOG_ERR, "DTLS - Can't init ciphers '%s' at '%s' : %s", conn->dtls_cipher,
		       errpos, gnutls_strerror(rc));
		dtls_gnutls_data_destroy(d);
		return 0;
	}


	rc = gnutls_priority_set(d->session, d->priority_cache);
	if (rc < 0) {
		cw_log(LOG_ERR, "DTLS - Can't set priority: %s", gnutls_strerror(rc));
		dtls_gnutls_data_destroy(d);
		return 0;
	}

*/
	rc = gnutls_priority_set_direct(d->session,conn->dtls_cipher,&errpos);
	if (rc < 0) {
		cw_log(LOG_ERR, "DTLS - Can't init ciphers '%s' at '%s' : %s", conn->dtls_cipher,
		       errpos, gnutls_strerror(rc));
		dtls_gnutls_data_destroy(d);
		return 0;
	}

	


	rc = gnutls_credentials_set(d->session, GNUTLS_CRD_CERTIFICATE, d->x509_cred);
	if (rc < 0) {
		cw_log(LOG_ERR, "DTLS - Can't set x.509 credentials: %s", gnutls_strerror(rc));
		dtls_gnutls_data_destroy(d);
		return 0;
	}

	gnutls_certificate_set_verify_function(d->x509_cred,verify_cert);
	gnutls_session_set_ptr(d->session, conn);
	gnutls_transport_set_ptr(d->session, conn);
	gnutls_transport_set_pull_function(d->session, dtls_gnutls_bio_read);
	gnutls_transport_set_push_function(d->session, dtls_gnutls_bio_write);
	gnutls_transport_set_pull_timeout_function(d->session, dtls_gnutls_bio_wait);


#if GNUTLS_VERSION_NUMBER >= 0x030100
	gnutls_handshake_set_timeout(d->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
	gnutls_dtls_set_data_mtu(d->session, conn->dtls_mtu);
#endif
	gnutls_dtls_set_mtu(d->session, conn->dtls_mtu);




	return d;
}
Exemple #3
0
int dtls_try_handshake(struct openconnect_info *vpninfo)
{
	int err = gnutls_handshake(vpninfo->new_dtls_ssl);

	if (!err) {
#ifdef HAVE_GNUTLS_DTLS_SET_DATA_MTU
		/* Make sure GnuTLS's idea of the MTU is sufficient to take
		   a full VPN MTU (with 1-byte header) in a data record. */
		err = gnutls_dtls_set_data_mtu(vpninfo->new_dtls_ssl, vpninfo->ip_info.mtu + 1);
		if (err) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Failed to set DTLS MTU: %s\n"),
				     gnutls_strerror(err));
			goto error;
		}
#else
		/* If we don't have gnutls_dtls_set_data_mtu() then make sure
		   we leave enough headroom by adding the worst-case overhead.
		   We only support AES128-CBC and DES-CBC3-SHA anyway, so
		   working out the worst case isn't hard. */
		gnutls_dtls_set_mtu(vpninfo->new_dtls_ssl,
				    vpninfo->ip_info.mtu + 1 /* packet + header */
				    + 13 /* DTLS header */
				    + 20 /* biggest supported MAC (SHA1) */
				    + 16 /* biggest supported IV (AES-128) */
				    + 16 /* max padding */);
#endif

		vpn_progress(vpninfo, PRG_INFO, _("Established DTLS connection (using GnuTLS)\n"));

		dtls_close(vpninfo, 0);
		vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
		vpninfo->dtls_fd = vpninfo->new_dtls_fd;

		vpninfo->new_dtls_ssl = NULL;
		vpninfo->new_dtls_fd = -1;

		vpninfo->dtls_times.last_rx = vpninfo->dtls_times.last_tx = time(NULL);

		/* XXX: For OpenSSL we explicitly prevent retransmits here. */
		return 0;
	}

	if (err == GNUTLS_E_AGAIN) {
		if (time(NULL) < vpninfo->new_dtls_started + 5)
			return 0;
		vpn_progress(vpninfo, PRG_TRACE, _("DTLS handshake timed out\n"));
	}

	vpn_progress(vpninfo, PRG_ERR, _("DTLS handshake failed: %s\n"),
		     gnutls_strerror(err));

 error:
	/* Kill both the new (failed) connection and the old one too. The
	   only time there'll be a valid existing session is when it was a
	   rekey, and in that case it's time for the old one to die. */
	dtls_close(vpninfo, 1);

	time(&vpninfo->new_dtls_started);
	return -EINVAL;
}