Example #1
0
int
main (void)
{
  /* credentials */
  gnutls_anon_client_credentials_t c_anoncred;
  gnutls_certificate_credentials_t c_certcred;
  
  gnutls_session_t client;
  int sd, i;

  /* General init. */
  gnutls_global_init ();
  ecore_init();
//  gnutls_global_set_log_function (tls_log_func);
//  gnutls_global_set_log_level (2);

  /* Init client */
  gnutls_anon_allocate_client_credentials (&c_anoncred);
  gnutls_certificate_allocate_credentials (&c_certcred);


  for (i=0;i<5;i++) 
    {

      gnutls_init (&client, GNUTLS_CLIENT);
      /* set very specific priorities */
      gnutls_priority_set_direct(client, "NORMAL:+ANON-DH", NULL);
      gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred);
      gnutls_credentials_set (client, GNUTLS_CRD_CERTIFICATE, c_certcred);
      gnutls_server_name_set(client, GNUTLS_NAME_DNS, "localhost", strlen("localhost"));

      /* connect to the peer
       */
      sd = tcp_connect ();

      /* associate gnutls with socket */
      gnutls_transport_set_ptr (client, (gnutls_transport_ptr_t) sd);
      /* add a callback for data being available for send/receive on socket */
      if (!ecore_main_fd_handler_add(sd, ECORE_FD_READ | ECORE_FD_WRITE, (Ecore_Fd_Cb)_process_data, client, NULL, NULL))
        {
           print("could not create fd handler!");
           exit(1);
        }
      /* begin main loop */
      ecore_main_loop_begin();

      gnutls_bye (client, GNUTLS_SHUT_RDWR);

      gnutls_deinit (client);

      tcp_close (sd);
    }
  
  return 0;
}
Example #2
0
LIBETPAN_EXPORT
int mailstream_ssl_set_server_name(struct mailstream_ssl_context * ssl_context,
    char * hostname)
{
  int r = -1;

#ifdef USE_SSL
# ifdef USE_GNUTLS
  if (hostname != NULL) {
    r = gnutls_server_name_set(ssl_context->session, GNUTLS_NAME_DNS, hostname, strlen(hostname));
  }
  else {
    r = gnutls_server_name_set(ssl_context->session, GNUTLS_NAME_DNS, "", 0U);
  }
# else /* !USE_GNUTLS */
#  if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
  if (hostname != NULL) {
    /* Unfortunately we can't set this in the openssl session yet since it
     * hasn't been created yet; we only have the openssl context at this point.
     * We will set it in the openssl session when we create it, soon after the
     * client callback that we expect to be calling us (since it is the way the
     * client gets our mailstream_ssl_context) returns (see
     * ssl_data_new_full()) but we cannot rely on the client persisting it. We
     * must therefore take a temporary copy here, which we free once we've set
     * it in the openssl session. */
    ssl_context->server_name = strdup(hostname);
  }
  else {
    if (ssl_context->server_name != NULL) {
      free(ssl_context->server_name);
    }
    ssl_context->server_name = NULL;
  }
  r = 0;
#  endif /* (OPENSSL_VERSION_NUMBER >= 0x10000000L) */
# endif /* !USE_GNUTLS */
#endif /* USE_SSL */

  return r;
}
Example #3
0
/* initializes a gnutls_session with some defaults.
 */
static gnutls_session
init_tls_session (const char *hostname)
{
  gnutls_session session;

  gnutls_init (&session, GNUTLS_CLIENT);

  /* allow the use of private ciphersuites.
   */
  if (disable_extensions == 0)
    {
      gnutls_handshake_set_private_extensions (session, 1);
      gnutls_server_name_set (session, GNUTLS_NAME_DNS, hostname,
			      strlen (hostname));
      gnutls_certificate_type_set_priority (session, cert_type_priority);
    }

  gnutls_cipher_set_priority (session, cipher_priority);
  gnutls_compression_set_priority (session, comp_priority);
  gnutls_kx_set_priority (session, kx_priority);
  gnutls_protocol_set_priority (session, protocol_priority);
  gnutls_mac_set_priority (session, mac_priority);


  gnutls_dh_set_prime_bits (session, 512);

  gnutls_credentials_set (session, GNUTLS_CRD_ANON, anon_cred);
  gnutls_credentials_set (session, GNUTLS_CRD_SRP, srp_cred);
  gnutls_credentials_set (session, GNUTLS_CRD_PSK, psk_cred);
  gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred);

  gnutls_certificate_client_set_retrieve_function (xcred, cert_callback);

  /* send the fingerprint */
  if (fingerprint != 0)
    gnutls_openpgp_send_key (session, GNUTLS_OPENPGP_KEY_FINGERPRINT);

  /* use the max record size extension */
  if (record_max_size > 0 && disable_extensions == 0)
    {
      if (gnutls_record_set_max_size (session, record_max_size) < 0)
	{
	  fprintf (stderr,
		   "Cannot set the maximum record size to %d.\n",
		   record_max_size);
	  fprintf (stderr, "Possible values: 512, 1024, 2048, 4096.\n");
	  exit (1);
	}
    }

  return session;
}
Example #4
0
int ssl_open(http_t *client, char *msg)
{
	char buf[256];
	const char *sn;
	const X509 *cert;

	if (!client->ssl_enabled)
		return tcp_init(&client->tcp, msg);

	tcp_set_port(&client->tcp, 443);
	DO(tcp_init(&client->tcp, msg));

	logit(LOG_INFO, "%s, initiating HTTPS ...", msg);
	client->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
	if (!client->ssl_ctx)
		return RC_HTTPS_OUT_OF_MEMORY;

	client->ssl = SSL_new(client->ssl_ctx);
	if (!client->ssl)
		return RC_HTTPS_OUT_OF_MEMORY;

	/* SSL SNI support: tell the servername we want to speak to */
	http_get_remote_name(client, &sn);
	if (gnutls_server_name_set(client->ssl->gnutls_state, GNUTLS_NAME_DNS, sn, strlen(sn)))
		return RC_HTTPS_SNI_ERROR;

	SSL_set_fd(client->ssl, client->tcp.ip.socket);
	if (-1 == SSL_connect(client->ssl))
		return RC_HTTPS_FAILED_CONNECT;

	logit(LOG_INFO, "SSL connection using %s", SSL_get_cipher(client->ssl));

	/* Get server's certificate (note: beware of dynamic allocation) - opt */
	cert = SSL_get_peer_certificate(client->ssl);
	if (!cert)
		return RC_HTTPS_FAILED_GETTING_CERT;

	/* Logging some cert details. Please note: X509_NAME_oneline doesn't
	   work when giving NULL instead of a buffer. */
	X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
	logit(LOG_INFO, "SSL server cert subject: %s", buf);
	X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
	logit(LOG_INFO, "SSL server cert issuer: %s", buf);

	/* We could do all sorts of certificate verification stuff here before
	   deallocating the certificate. */
	X509_free(cert);

	return 0;
}
int
main (void)
{
  /* credentials */
  gnutls_anon_client_credentials_t c_anoncred;
  gnutls_certificate_credentials_t c_certcred;
  
  gnutls_session_t client;
  int sd;

  /* General init. */
  gnutls_global_init ();
  ecore_init();
  gnutls_global_set_log_function (tls_log_func);
    gnutls_global_set_log_level (6);

  /* Init client */
  gnutls_anon_allocate_client_credentials (&c_anoncred);
  gnutls_certificate_allocate_credentials (&c_certcred);
  gnutls_init (&client, GNUTLS_CLIENT);
  /* set very specific priorities */
  gnutls_priority_set_direct(client, "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", NULL);
  gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred);
  gnutls_credentials_set (client, GNUTLS_CRD_CERTIFICATE, c_certcred);
  gnutls_server_name_set(client, GNUTLS_NAME_DNS, "www.verisign.com", strlen("www.verisign.com"));


  /* connect to the peer
   */
  sd = tcp_connect ();

  /* associate gnutls with socket */
  gnutls_transport_set_ptr (client, (gnutls_transport_ptr_t) sd);
  /* add a callback for data being available for send/receive on socket */
  if (!ecore_main_fd_handler_add(sd, ECORE_FD_READ | ECORE_FD_WRITE, (Ecore_Fd_Cb)_process_data, client, NULL, NULL))
    {
       print("could not create fd handler!");
       exit(1);
    }
  /* begin main loop */
  ecore_main_loop_begin();

  gnutls_bye (client, GNUTLS_SHUT_RDWR);

  gnutls_deinit (client);

  tcp_close (sd);
  
  return 0;
}
Example #6
0
static int get_cert(socket_st *hd, const char *hostname, unsigned udp, int fd)
{
	gnutls_certificate_credentials_t xcred;
	gnutls_session_t session;
	int ret;
	struct priv_st priv;

	priv.found = 0;
	priv.fd = fd;

	ret = gnutls_certificate_allocate_credentials(&xcred);
	if (ret < 0) {
		fprintf(stderr, "error[%d]: %s\n", __LINE__,
			gnutls_strerror(ret));
		exit(1);
	}
	gnutls_certificate_set_verify_function(xcred, cert_callback);

	ret = gnutls_init(&session, (udp?GNUTLS_DATAGRAM:0)|GNUTLS_CLIENT);
	if (ret < 0) {
		fprintf(stderr, "error[%d]: %s\n", __LINE__,
			gnutls_strerror(ret));
		exit(1);
	}
	gnutls_session_set_ptr(session, &priv);
	gnutls_transport_set_int(session, hd->fd);

	gnutls_set_default_priority(session);
	if (hostname && is_ip(hostname)==0) {
		gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname, strlen(hostname));
	}
	gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);

	do {
		ret = gnutls_handshake(session);
	} while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_WARNING_ALERT_RECEIVED);
	/* we don't care on the result */

	gnutls_deinit(session);
	gnutls_certificate_free_credentials(xcred);

	if (priv.found == 0)
		return -1;

	return 0;
}
Example #7
0
int CTlsSocket::Handshake(const CTlsSocket* pPrimarySocket, bool try_resume)
{
	m_pOwner->LogMessage(MessageType::Debug_Verbose, _T("CTlsSocket::Handshake()"));
	wxASSERT(m_session);

	m_tlsState = TlsState::handshake;

	wxString hostname;

	if (pPrimarySocket) {
		// Implicitly trust certificate of primary socket
		unsigned int cert_list_size;
		const gnutls_datum_t* const cert_list = gnutls_certificate_get_peers(pPrimarySocket->m_session, &cert_list_size);
		if (cert_list && cert_list_size)
		{
			delete [] m_implicitTrustedCert.data;
			m_implicitTrustedCert.data = new unsigned char[cert_list[0].size];
			memcpy(m_implicitTrustedCert.data, cert_list[0].data, cert_list[0].size);
			m_implicitTrustedCert.size = cert_list[0].size;
		}

		if (try_resume)
		{
			if (!CopySessionData(pPrimarySocket))
				return FZ_REPLY_ERROR;
		}

		hostname = pPrimarySocket->m_pSocket->GetPeerHost();
	}
	else {
		hostname = m_pSocket->GetPeerHost();
	}

	if( !hostname.empty() && !IsIpAddress(hostname) ) {
		const wxWX2MBbuf utf8 = hostname.mb_str(wxConvUTF8);
		if( utf8 ) {
			int res = gnutls_server_name_set( m_session, GNUTLS_NAME_DNS, utf8, strlen(utf8) );
			if( res ) {
				LogError(res, _T("gnutls_server_name_set"), MessageType::Debug_Warning );
			}
		}
	}

	return ContinueHandshake();
}
Example #8
0
int CTlsSocket::Handshake(const CTlsSocket* pPrimarySocket, bool try_resume)
{
	m_pOwner->LogMessage(MessageType::Debug_Verbose, _T("CTlsSocket::Handshake()"));
	wxASSERT(m_session);

	m_tlsState = TlsState::handshake;

	fz::native_string hostname;

	if (pPrimarySocket) {
		// Implicitly trust certificate of primary socket
		unsigned int cert_list_size;
		const gnutls_datum_t* const cert_list = gnutls_certificate_get_peers(pPrimarySocket->m_session, &cert_list_size);
		if (cert_list && cert_list_size) {
			delete [] m_implicitTrustedCert.data;
			m_implicitTrustedCert.data = new unsigned char[cert_list[0].size];
			memcpy(m_implicitTrustedCert.data, cert_list[0].data, cert_list[0].size);
			m_implicitTrustedCert.size = cert_list[0].size;
		}

		if (try_resume) {
			if (!CopySessionData(pPrimarySocket))
				return FZ_REPLY_ERROR;
		}

		hostname = pPrimarySocket->m_socket.GetPeerHost();
	}
	else {
		hostname = m_socket.GetPeerHost();
	}

	if (!hostname.empty() && fz::get_address_type(hostname) == fz::address_type::unknown) {
		auto const utf8 = fz::to_utf8(hostname);
		if (!utf8.empty()) {
			int res = gnutls_server_name_set(m_session, GNUTLS_NAME_DNS, utf8.c_str(), utf8.size());
			if (res) {
				LogError(res, _T("gnutls_server_name_set"), MessageType::Debug_Warning );
			}
		}
	}

	gnutls_handshake_set_hook_function(m_session, GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_BOTH, &handshake_hook_func);

	return ContinueHandshake();
}
static void
g_tls_client_connection_gnutls_set_property (GObject      *object,
					     guint         prop_id,
					     const GValue *value,
					     GParamSpec   *pspec)
{
  GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (object);
  const char *hostname;

  switch (prop_id)
    {
    case PROP_VALIDATION_FLAGS:
      gnutls->priv->validation_flags = g_value_get_flags (value);
      break;

    case PROP_SERVER_IDENTITY:
      if (gnutls->priv->server_identity)
	g_object_unref (gnutls->priv->server_identity);
      gnutls->priv->server_identity = g_value_dup_object (value);

      hostname = get_server_identity (gnutls);
      if (hostname)
	{
	  gnutls_session_t session = g_tls_connection_gnutls_get_session (G_TLS_CONNECTION_GNUTLS (gnutls));

	  gnutls_server_name_set (session, GNUTLS_NAME_DNS,
				  hostname, strlen (hostname));
	}
      break;

    case PROP_USE_SSL3:
      gnutls->priv->use_ssl3 = g_value_get_boolean (value);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}
Example #10
0
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
{
    TLSContext *p = h->priv_data;
    TLSShared *c = &p->tls_shared;
    int ret;

    ff_gnutls_init();

    if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0)
        goto fail;

    gnutls_init(&p->session, c->listen ? GNUTLS_SERVER : GNUTLS_CLIENT);
    if (!c->listen && !c->numerichost)
        gnutls_server_name_set(p->session, GNUTLS_NAME_DNS, c->host, strlen(c->host));
    gnutls_certificate_allocate_credentials(&p->cred);
    if (c->ca_file) {
        ret = gnutls_certificate_set_x509_trust_file(p->cred, c->ca_file, GNUTLS_X509_FMT_PEM);
        if (ret < 0)
            av_log(h, AV_LOG_ERROR, "%s\n", gnutls_strerror(ret));
    }
#if GNUTLS_VERSION_MAJOR >= 3
    else
        gnutls_certificate_set_x509_system_trust(p->cred);
#endif
    gnutls_certificate_set_verify_flags(p->cred, c->verify ?
                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT : 0);
    if (c->cert_file && c->key_file) {
        ret = gnutls_certificate_set_x509_key_file(p->cred,
                                                   c->cert_file, c->key_file,
                                                   GNUTLS_X509_FMT_PEM);
        if (ret < 0) {
            av_log(h, AV_LOG_ERROR,
                   "Unable to set cert/key files %s and %s: %s\n",
                   c->cert_file, c->key_file, gnutls_strerror(ret));
            ret = AVERROR(EIO);
            goto fail;
        }
    } else if (c->cert_file || c->key_file)
        av_log(h, AV_LOG_ERROR, "cert and key required\n");
    gnutls_credentials_set(p->session, GNUTLS_CRD_CERTIFICATE, p->cred);
    gnutls_transport_set_pull_function(p->session, gnutls_url_pull);
    gnutls_transport_set_push_function(p->session, gnutls_url_push);
    gnutls_transport_set_ptr(p->session, c->tcp);
    gnutls_priority_set_direct(p->session, "NORMAL", NULL);
    ret = gnutls_handshake(p->session);
    if (ret) {
        ret = print_tls_error(h, ret);
        goto fail;
    }
    p->need_shutdown = 1;
    if (c->verify) {
        unsigned int status, cert_list_size;
        gnutls_x509_crt_t cert;
        const gnutls_datum_t *cert_list;
        if ((ret = gnutls_certificate_verify_peers2(p->session, &status)) < 0) {
            av_log(h, AV_LOG_ERROR, "Unable to verify peer certificate: %s\n",
                                    gnutls_strerror(ret));
            ret = AVERROR(EIO);
            goto fail;
        }
        if (status & GNUTLS_CERT_INVALID) {
            av_log(h, AV_LOG_ERROR, "Peer certificate failed verification\n");
            ret = AVERROR(EIO);
            goto fail;
        }
        if (gnutls_certificate_type_get(p->session) != GNUTLS_CRT_X509) {
            av_log(h, AV_LOG_ERROR, "Unsupported certificate type\n");
            ret = AVERROR(EIO);
            goto fail;
        }
        gnutls_x509_crt_init(&cert);
        cert_list = gnutls_certificate_get_peers(p->session, &cert_list_size);
        gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER);
        ret = gnutls_x509_crt_check_hostname(cert, c->host);
        gnutls_x509_crt_deinit(cert);
        if (!ret) {
            av_log(h, AV_LOG_ERROR,
                   "The certificate's owner does not match hostname %s\n", c->host);
            ret = AVERROR(EIO);
            goto fail;
        }
    }

    return 0;
fail:
    tls_close(h);
    return ret;
}
PresentationServer::PresentationServer(const std::string & conferenceUrl,
		const std::string & managerHost, unsigned short managerPort,
		int screenWidth, int screenHeight,
		const std::string & caCertificate,
		const std::string & managerPath, const std::string & managerParam) :
_server(0), _fps(5) {

	if (caCertificate.empty()) {
		throw std::invalid_argument("no CA Certificate provided!");
	}
	//Erstmal d�rfte jetzt die Authorisierung und die Anfrage an den Manager geschehen
	//Dazu einfach �ber nen Socket ne primitive http anfrage senden und die Antwort auswerten
	//Achtung momentan ist BUF_SIZE auch die maximale Nachrichtengr��e die Empfangen werden kann!!
	//@TODO Dringend ne bessere HTTP Implementation verwenden oder selber bauen.
	const int BUF_SIZE = 2048;
	char tmpBuffer[BUF_SIZE];
	SOCKET httpSocket = rfbConnectToTcpAddr(const_cast<char*> (managerHost.c_str()), managerPort);
	std::string httpResponse;
	if (httpSocket == INVALID_SOCKET) {
		std::cerr << "Failed to connect to " << managerHost << ":" << managerPort << std::endl;
		throw std::runtime_error(STR_ERR_WEBHOST_UNREACHABLE);
		return;
	}

	//HTTPS Verbindung mit GnuTLS und handkodierter HTTP Nachricht :)
	gnutls_session_t session = 0;
	gnutls_certificate_credentials_t credentials = 0;
	gnutls_datum_t data;
	int gtlsRet = GNUTLS_E_SUCCESS;
	try {
		//Zertifikat
		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_certificate_allocate_credentials(&credentials))) {
			std::cerr << "failed to allocate credentials." << std::endl;
			throw std::runtime_error("failed to allocate credentials.");
		}

		data.size = caCertificate.size();
		data.data = (unsigned char*) caCertificate.data();
		gnutls_certificate_set_x509_trust_mem(credentials, &data, GNUTLS_X509_FMT_PEM);
		
		// Verifizierung des Zertifikats in der übergebenen Callback Funktion, Ausführung erfolgt als Teil des Handshakes
		gnutls_certificate_set_verify_function(credentials, [] (gnutls_session_t session) throw () -> int {
			std::cout << "verifying certificate...";
			//Server Zertifikat prüfen:
			unsigned int verify = 0;
			if (GNUTLS_E_SUCCESS != gnutls_certificate_verify_peers3(session, (const char*) gnutls_session_get_ptr(session), &verify)) {
				std::cerr << "certficate verification failed." << std::endl;
				return -1;
			}
			if (verify != 0) {
				gnutls_datum_t pr;
				std::cout << "no" << std::endl;
				gnutls_certificate_verification_status_print(verify, GNUTLS_CRT_X509, &pr, 0);
				std::cerr << pr.data << std::endl;
				free(pr.data);
				return -2;
			}
			std::cout << "yes" << std::endl;
			return 0;
		});
		//Session
		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_init(&session, GNUTLS_CLIENT))) {
			std::cerr << "failed to init session." << std::endl;
			throw std::runtime_error("failed to init session.");
		}

		gnutls_server_name_set(session, GNUTLS_NAME_DNS, managerHost.data(), managerHost.length());
		gnutls_session_set_ptr(session, (void*) managerHost.c_str());

		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_priority_set_direct(session, CIPHERSUITE_PRIORITIES, 0))) {
			std::cerr << "failed to set priority." << std::endl;
			throw std::runtime_error("failed to set priority.");
		}

		gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, credentials);
		gnutls_transport_set_int(session, httpSocket);
		gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
		if (GNUTLS_E_SUCCESS != ((gtlsRet = gnutls_handshake(session)))) {
			std::cerr << "handshake failed." << std::endl;
			throw std::runtime_error("handshake failed.");
		}

		//Ciphersuite 
		std::cout << "ciphersuite: " << gnutls_cipher_suite_get_name(gnutls_kx_get(session), gnutls_cipher_get(session), gnutls_mac_get(session)) << std::endl;
		//Prepare HTTP Request
		std::string httpRequest;
		std::string httpRequestBody = managerParam + "=" + urlencode(conferenceUrl) + "&version=" + std::to_string(TOOL_VERSION);
		httpRequest += "POST ";
		httpRequest += managerPath;
		httpRequest += " HTTP/1.1\r\n";
		httpRequest += "Host: ";
		httpRequest += managerHost + "\r\n";
		httpRequest += "Content-Type: application/x-www-form-urlencoded\r\n"; //< Beachte der Webserver kann auf der Zielroute momentan auch nichts anderes
		httpRequest += "Connection: close\r\n";
		sprintf(tmpBuffer, "%d", httpRequestBody.length());
		httpRequest += "Content-Length: " + std::string(tmpBuffer) + "\r\n";
		httpRequest += "\r\n";
		httpRequest += httpRequestBody;

		std::cout << "SEND >>" << std::endl << httpRequest << std::endl << "<<" << std::endl;

		gnutls_record_send(session, httpRequest.data(), httpRequest.length());

		std::cout << "WAITING TO RECEIVE.." << std::endl;
		//Alles lesen und hoffen dass sich der Webserver dran h�lt und die Verbindung schlie�t
		//wenn er fertig mit Senden ist
		int c = 0, r = 0;

		do {
			r = gnutls_record_recv(session, tmpBuffer + c, BUF_SIZE - c);
			if (r > 0) c += r;
		} while (r > 0 && c < BUF_SIZE);

		if (c > 1024 || c <= 0) {
			std::cout << "received " << c << " bytes" << std::endl;
			std::cout << std::string(tmpBuffer, c) << std::endl;
			std::cerr << "Couldn't receive answer." << std::endl;
			throw std::runtime_error(STR_ERR_WRONG_ANSWER);
		}

		httpResponse = std::string(tmpBuffer, c);

		//Und fertig Verbindung beenden
		gnutls_bye(session, GNUTLS_SHUT_RDWR);
		gnutls_deinit(session);
		gnutls_certificate_free_credentials(credentials);
		closesocket(httpSocket);
	} catch (...) {
		//Irgendein Fehler trat auf, dann schließen.
		std::cerr << gtlsRet << ' ' << gnutls_error_is_fatal(gtlsRet) << std::endl;
		std::cerr << gnutls_strerror(gtlsRet) << std::endl;
		std::cerr << gnutls_alert_get_name(gnutls_alert_get(session)) << std::endl;
		if (session) gnutls_deinit(session);
		if (credentials) gnutls_certificate_free_credentials(credentials);
		closesocket(httpSocket);
		throw std::runtime_error(STR_ERR_TLS_FAILED); //weiterschmeißen
	}
	std::cout << "RECV >>" << std::endl << httpResponse << std::endl << "<<" << std::endl;
	/**
		Antwort sollte jetzt der typische HTTP Antwortquark sein und als Inhalt
		sollte ein Text der folgenden Form sein:

		PresentationServerUseHost: <host>\n
		PresentationServerUsePort: <port>\n
	 */
	unsigned short port;
	std::string host;
	int lifetime;

	try {
		_messageBox = utf8_to_ucs2(getParameter(httpResponse, "MessageBox", ""));
		port = atoi(getParameter(httpResponse, "PresentationServerUsePort").c_str());
		host = getParameter(httpResponse, "PresentationServerUseHost");
		_demo = atoi(getParameter(httpResponse, "Demo", "0").c_str()) ? true : false;
		lifetime = atoi(getParameter(httpResponse, "RuntimeSec", "0").c_str());
		_serverPassword = getParameter(httpResponse, "PresentationServerPassword");
	} catch (std::runtime_error e) {
		if (!_messageBox.empty())
			throw runtime_error_with_extra_msg(_messageBox, getParameter(httpResponse, "Message"));
		throw std::runtime_error(getParameter(httpResponse, "Message"));
	}

	//Wenn die erfolgreich war dann den Server erstellen, Gr��e = Desktopgr��e
	_initRfbServer(screenWidth, screenHeight, _serverPassword, managerHost, caCertificate, host, port);

	if (lifetime > 0) {
		_timeOfDeath = std::chrono::system_clock::now() + std::chrono::seconds(lifetime);
		_useTimeOfDeath = true;
	} else {
		_useTimeOfDeath = false;
	}
}
Example #12
0
/**
 * tls_negotiate - Negotiate TLS connection
 * @param conn Connection to a server
 * @retval  0 Success
 * @retval -1 Error
 *
 * After TLS state has been initialized, attempt to negotiate TLS over the
 * wire, including certificate checks.
 */
static int tls_negotiate(struct Connection *conn)
{
  struct TlsSockData *data = mutt_mem_calloc(1, sizeof(struct TlsSockData));
  conn->sockdata = data;
  int err = gnutls_certificate_allocate_credentials(&data->xcred);
  if (err < 0)
  {
    FREE(&conn->sockdata);
    mutt_error("gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err));
    return -1;
  }

  gnutls_certificate_set_x509_trust_file(data->xcred, C_CertificateFile, GNUTLS_X509_FMT_PEM);
  /* ignore errors, maybe file doesn't exist yet */

  if (C_SslCaCertificatesFile)
  {
    gnutls_certificate_set_x509_trust_file(data->xcred, C_SslCaCertificatesFile,
                                           GNUTLS_X509_FMT_PEM);
  }

  if (C_SslClientCert)
  {
    mutt_debug(LL_DEBUG2, "Using client certificate %s\n", C_SslClientCert);
    gnutls_certificate_set_x509_key_file(data->xcred, C_SslClientCert,
                                         C_SslClientCert, GNUTLS_X509_FMT_PEM);
  }

#ifdef HAVE_DECL_GNUTLS_VERIFY_DISABLE_TIME_CHECKS
  /* disable checking certificate activation/expiration times
   * in gnutls, we do the checks ourselves */
  gnutls_certificate_set_verify_flags(data->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
#endif

  err = gnutls_init(&data->state, GNUTLS_CLIENT);
  if (err)
  {
    mutt_error("gnutls_handshake: %s", gnutls_strerror(err));
    goto fail;
  }

  /* set socket */
  gnutls_transport_set_ptr(data->state, (gnutls_transport_ptr_t)(long) conn->fd);

  if (gnutls_server_name_set(data->state, GNUTLS_NAME_DNS, conn->account.host,
                             mutt_str_strlen(conn->account.host)))
  {
    mutt_error(_("Warning: unable to set TLS SNI host name"));
  }

  if (tls_set_priority(data) < 0)
  {
    goto fail;
  }

  if (C_SslMinDhPrimeBits > 0)
  {
    gnutls_dh_set_prime_bits(data->state, C_SslMinDhPrimeBits);
  }

  /* gnutls_set_cred (data->state, GNUTLS_ANON, NULL); */

  gnutls_credentials_set(data->state, GNUTLS_CRD_CERTIFICATE, data->xcred);

  err = gnutls_handshake(data->state);

  while (err == GNUTLS_E_AGAIN)
  {
    err = gnutls_handshake(data->state);
  }
  if (err < 0)
  {
    if (err == GNUTLS_E_FATAL_ALERT_RECEIVED)
    {
      mutt_error("gnutls_handshake: %s(%s)", gnutls_strerror(err),
                 gnutls_alert_get_name(gnutls_alert_get(data->state)));
    }
    else
    {
      mutt_error("gnutls_handshake: %s", gnutls_strerror(err));
    }
    goto fail;
  }

  if (tls_check_certificate(conn) == 0)
    goto fail;

  /* set Security Strength Factor (SSF) for SASL */
  /* NB: gnutls_cipher_get_key_size() returns key length in bytes */
  conn->ssf = gnutls_cipher_get_key_size(gnutls_cipher_get(data->state)) * 8;

  tls_get_client_cert(conn);

  if (!OptNoCurses)
  {
    mutt_message(_("SSL/TLS connection using %s (%s/%s/%s)"),
                 gnutls_protocol_get_name(gnutls_protocol_get_version(data->state)),
                 gnutls_kx_get_name(gnutls_kx_get(data->state)),
                 gnutls_cipher_get_name(gnutls_cipher_get(data->state)),
                 gnutls_mac_get_name(gnutls_mac_get(data->state)));
    mutt_sleep(0);
  }

  return 0;

fail:
  gnutls_certificate_free_credentials(data->xcred);
  gnutls_deinit(data->state);
  FREE(&conn->sockdata);
  return -1;
}
Example #13
0
int main(void)
{
        int ret, sd, ii;
        gnutls_session_t session;
        char buffer[MAX_BUF + 1];
        gnutls_certificate_credentials_t xcred;

        if (gnutls_check_version("3.1.4") == NULL) {
                fprintf(stderr, "GnuTLS 3.1.4 or later is required for this example\n");
                exit(1);
        }

        /* for backwards compatibility with gnutls < 3.3.0 */
        CHECK(gnutls_global_init());

        /* X509 stuff */
        CHECK(gnutls_certificate_allocate_credentials(&xcred));

        /* sets the system trusted CAs for Internet PKI */
        CHECK(gnutls_certificate_set_x509_system_trust(xcred));

        /* Initialize TLS session */
        CHECK(gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_DATAGRAM));

        /* Use default priorities */
        CHECK(gnutls_set_default_priority(session));

        /* put the x509 credentials to the current session */
        CHECK(gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred));
        CHECK(gnutls_server_name_set(session, GNUTLS_NAME_DNS, "www.example.com",
                                     strlen("www.example.com")));

        gnutls_session_set_verify_cert(session, "www.example.com", 0);

        /* connect to the peer */
        sd = udp_connect();

        gnutls_transport_set_int(session, sd);

        /* set the connection MTU */
        gnutls_dtls_set_mtu(session, 1000);
        /* gnutls_dtls_set_timeouts(session, 1000, 60000); */

        /* Perform the TLS handshake */
        do {
                ret = gnutls_handshake(session);
        }
        while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
        /* Note that DTLS may also receive GNUTLS_E_LARGE_PACKET */

        if (ret < 0) {
                fprintf(stderr, "*** Handshake failed\n");
                gnutls_perror(ret);
                goto end;
        } else {
                char *desc;

                desc = gnutls_session_get_desc(session);
                printf("- Session info: %s\n", desc);
                gnutls_free(desc);
        }

        LOOP_CHECK(ret, gnutls_record_send(session, MSG, strlen(MSG)));

        LOOP_CHECK(ret, gnutls_record_recv(session, buffer, MAX_BUF));
        if (ret == 0) {
                printf("- Peer has closed the TLS connection\n");
                goto end;
        } else if (ret < 0 && gnutls_error_is_fatal(ret) == 0) {
                fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret));
        } else if (ret < 0) {
                fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret));
                goto end;
        }

        if (ret > 0) {
                printf("- Received %d bytes: ", ret);
                for (ii = 0; ii < ret; ii++) {
                        fputc(buffer[ii], stdout);
                }
                fputs("\n", stdout);
        }

        /* It is suggested not to use GNUTLS_SHUT_RDWR in DTLS
         * connections because the peer's closure message might
         * be lost */
        CHECK(gnutls_bye(session, GNUTLS_SHUT_WR));

      end:

        udp_close(sd);

        gnutls_deinit(session);

        gnutls_certificate_free_credentials(xcred);

        gnutls_global_deinit();

        return 0;
}
Example #14
0
static CURLcode
gtls_connect_step1(struct connectdata *conn,
                   int sockindex)
{
#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
  static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
#endif
  struct SessionHandle *data = conn->data;
  gnutls_session session;
  int rc;
  void *ssl_sessionid;
  size_t ssl_idsize;
  bool sni = TRUE; /* default is SNI enabled */
#ifdef ENABLE_IPV6
  struct in6_addr addr;
#else
  struct in_addr addr;
#endif

  if(conn->ssl[sockindex].state == ssl_connection_complete)
    /* to make us tolerant against being called more than once for the
       same connection */
    return CURLE_OK;

  if(!gtls_inited)
    Curl_gtls_init();

  /* GnuTLS only supports SSLv3 and TLSv1 */
  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
    failf(data, "GnuTLS does not support SSLv2");
    return CURLE_SSL_CONNECT_ERROR;
  }
  else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
    sni = FALSE; /* SSLv3 has no SNI */

  /* allocate a cred struct */
  rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
  if(rc != GNUTLS_E_SUCCESS) {
    failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
    return CURLE_SSL_CONNECT_ERROR;
  }

#ifdef USE_TLS_SRP
  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
    infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);

    rc = gnutls_srp_allocate_client_credentials(
           &conn->ssl[sockindex].srp_client_cred);
    if(rc != GNUTLS_E_SUCCESS) {
      failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
            gnutls_strerror(rc));
      return CURLE_OUT_OF_MEMORY;
    }

    rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
                                           srp_client_cred,
                                           data->set.ssl.username,
                                           data->set.ssl.password);
    if(rc != GNUTLS_E_SUCCESS) {
      failf(data, "gnutls_srp_set_client_cred() failed: %s",
            gnutls_strerror(rc));
      return CURLE_BAD_FUNCTION_ARGUMENT;
    }
  }
#endif

  if(data->set.ssl.CAfile) {
    /* set the trusted CA cert bundle file */
    gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);

    rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
                                                data->set.ssl.CAfile,
                                                GNUTLS_X509_FMT_PEM);
    if(rc < 0) {
      infof(data, "error reading ca cert file %s (%s)\n",
            data->set.ssl.CAfile, gnutls_strerror(rc));
      if(data->set.ssl.verifypeer)
        return CURLE_SSL_CACERT_BADFILE;
    }
    else
      infof(data, "found %d certificates in %s\n",
            rc, data->set.ssl.CAfile);
  }

  if(data->set.ssl.CRLfile) {
    /* set the CRL list file */
    rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
                                              data->set.ssl.CRLfile,
                                              GNUTLS_X509_FMT_PEM);
    if(rc < 0) {
      failf(data, "error reading crl file %s (%s)",
            data->set.ssl.CRLfile, gnutls_strerror(rc));
      return CURLE_SSL_CRL_BADFILE;
    }
    else
      infof(data, "found %d CRL in %s\n",
            rc, data->set.ssl.CRLfile);
  }

  /* Initialize TLS session as a client */
  rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
  if(rc != GNUTLS_E_SUCCESS) {
    failf(data, "gnutls_init() failed: %d", rc);
    return CURLE_SSL_CONNECT_ERROR;
  }

  /* convenient assign */
  session = conn->ssl[sockindex].session;

  if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
#ifdef ENABLE_IPV6
     (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
#endif
     sni &&
     (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
                             strlen(conn->host.name)) < 0))
    infof(data, "WARNING: failed to configure server name indication (SNI) "
          "TLS extension\n");

  /* Use default priorities */
  rc = gnutls_set_default_priority(session);
  if(rc != GNUTLS_E_SUCCESS)
    return CURLE_SSL_CONNECT_ERROR;

  if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) {
#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
    static const int protocol_priority[] = { GNUTLS_SSL3, 0 };
    rc = gnutls_protocol_set_priority(session, protocol_priority);
#else
    const char *err;
    /* the combination of the cipher ARCFOUR with SSL 3.0 and TLS 1.0 is not
       vulnerable to attacks such as the BEAST, why this code now explicitly
       asks for that
    */
    rc = gnutls_priority_set_direct(session,
                                    "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0:"
                                    "-CIPHER-ALL:+ARCFOUR-128",
                                    &err);
#endif
    if(rc != GNUTLS_E_SUCCESS)
      return CURLE_SSL_CONNECT_ERROR;
  }

#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
  /* Sets the priority on the certificate types supported by gnutls. Priority
     is higher for types specified before others. After specifying the types
     you want, you must append a 0. */
  rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
  if(rc != GNUTLS_E_SUCCESS)
    return CURLE_SSL_CONNECT_ERROR;
#endif

  if(data->set.str[STRING_CERT]) {
    if(gnutls_certificate_set_x509_key_file(
         conn->ssl[sockindex].cred,
         data->set.str[STRING_CERT],
         data->set.str[STRING_KEY] ?
         data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
         do_file_type(data->set.str[STRING_CERT_TYPE]) ) !=
       GNUTLS_E_SUCCESS) {
      failf(data, "error reading X.509 key or certificate file");
      return CURLE_SSL_CONNECT_ERROR;
    }
  }

#ifdef USE_TLS_SRP
  /* put the credentials to the current session */
  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
    rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
                                conn->ssl[sockindex].srp_client_cred);
    if(rc != GNUTLS_E_SUCCESS)
      failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
  }
  else
#endif
    rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
                                conn->ssl[sockindex].cred);

  /* set the connection handle (file descriptor for the socket) */
  gnutls_transport_set_ptr(session,
                           GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));

  /* register callback functions to send and receive data. */
  gnutls_transport_set_push_function(session, Curl_gtls_push);
  gnutls_transport_set_pull_function(session, Curl_gtls_pull);

  /* lowat must be set to zero when using custom push and pull functions. */
  gnutls_transport_set_lowat(session, 0);

  /* This might be a reconnect, so we check for a session ID in the cache
     to speed up things */

  if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
    /* we got a session id, use it! */
    gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);

    /* Informational message */
    infof (data, "SSL re-using session ID\n");
  }

  return CURLE_OK;
}
Example #15
0
int					/* O - 0 on success, -1 on failure */
_httpTLSStart(http_t *http)		/* I - Connection to server */
{
  char			hostname[256],	/* Hostname */
			*hostptr;	/* Pointer into hostname */
  int			status;		/* Status of handshake */
  gnutls_certificate_credentials_t *credentials;
					/* TLS credentials */
  char			priority_string[1024];
					/* Priority string */


  DEBUG_printf(("3_httpTLSStart(http=%p)", http));

  if (tls_options < 0)
  {
    DEBUG_puts("4_httpTLSStart: Setting defaults.");
    _cupsSetDefaults();
    DEBUG_printf(("4_httpTLSStart: tls_options=%x", tls_options));
  }

  if (http->mode == _HTTP_MODE_SERVER && !tls_keypath)
  {
    DEBUG_puts("4_httpTLSStart: cupsSetServerCredentials not called.");
    http->error  = errno = EINVAL;
    http->status = HTTP_STATUS_ERROR;
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Server credentials not set."), 1);

    return (-1);
  }

  credentials = (gnutls_certificate_credentials_t *)
                    malloc(sizeof(gnutls_certificate_credentials_t));
  if (credentials == NULL)
  {
    DEBUG_printf(("8_httpStartTLS: Unable to allocate credentials: %s",
                  strerror(errno)));
    http->error  = errno;
    http->status = HTTP_STATUS_ERROR;
    _cupsSetHTTPError(HTTP_STATUS_ERROR);

    return (-1);
  }

  gnutls_certificate_allocate_credentials(credentials);
  status = gnutls_init(&http->tls, http->mode == _HTTP_MODE_CLIENT ? GNUTLS_CLIENT : GNUTLS_SERVER);
  if (!status)
    status = gnutls_set_default_priority(http->tls);

  if (status)
  {
    http->error  = EIO;
    http->status = HTTP_STATUS_ERROR;

    DEBUG_printf(("4_httpTLSStart: Unable to initialize common TLS parameters: %s", gnutls_strerror(status)));
    _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0);

    gnutls_deinit(http->tls);
    gnutls_certificate_free_credentials(*credentials);
    free(credentials);
    http->tls = NULL;

    return (-1);
  }

  if (http->mode == _HTTP_MODE_CLIENT)
  {
   /*
    * Client: get the hostname to use for TLS...
    */

    if (httpAddrLocalhost(http->hostaddr))
    {
      strlcpy(hostname, "localhost", sizeof(hostname));
    }
    else
    {
     /*
      * Otherwise make sure the hostname we have does not end in a trailing dot.
      */

      strlcpy(hostname, http->hostname, sizeof(hostname));
      if ((hostptr = hostname + strlen(hostname) - 1) >= hostname &&
	  *hostptr == '.')
	*hostptr = '\0';
    }

    status = gnutls_server_name_set(http->tls, GNUTLS_NAME_DNS, hostname, strlen(hostname));
  }
  else
  {
   /*
    * Server: get certificate and private key...
    */

    char	crtfile[1024],		/* Certificate file */
		keyfile[1024];		/* Private key file */
    int		have_creds = 0;		/* Have credentials? */

    if (http->fields[HTTP_FIELD_HOST][0])
    {
     /*
      * Use hostname for TLS upgrade...
      */

      strlcpy(hostname, http->fields[HTTP_FIELD_HOST], sizeof(hostname));
    }
    else
    {
     /*
      * Resolve hostname from connection address...
      */

      http_addr_t	addr;		/* Connection address */
      socklen_t		addrlen;	/* Length of address */

      addrlen = sizeof(addr);
      if (getsockname(http->fd, (struct sockaddr *)&addr, &addrlen))
      {
	DEBUG_printf(("4_httpTLSStart: Unable to get socket address: %s", strerror(errno)));
	hostname[0] = '\0';
      }
      else if (httpAddrLocalhost(&addr))
	hostname[0] = '\0';
      else
      {
	httpAddrLookup(&addr, hostname, sizeof(hostname));
        DEBUG_printf(("4_httpTLSStart: Resolved socket address to \"%s\".", hostname));
      }
    }

    if (isdigit(hostname[0] & 255) || hostname[0] == '[')
      hostname[0] = '\0';		/* Don't allow numeric addresses */

    if (hostname[0])
    {
      http_gnutls_make_path(crtfile, sizeof(crtfile), tls_keypath, hostname, "crt");
      http_gnutls_make_path(keyfile, sizeof(keyfile), tls_keypath, hostname, "key");

      have_creds = !access(crtfile, 0) && !access(keyfile, 0);
    }
    else if (tls_common_name)
    {
      http_gnutls_make_path(crtfile, sizeof(crtfile), tls_keypath, tls_common_name, "crt");
      http_gnutls_make_path(keyfile, sizeof(keyfile), tls_keypath, tls_common_name, "key");

      have_creds = !access(crtfile, 0) && !access(keyfile, 0);
    }

    if (!have_creds && tls_auto_create && (hostname[0] || tls_common_name))
    {
      DEBUG_printf(("4_httpTLSStart: Auto-create credentials for \"%s\".", hostname[0] ? hostname : tls_common_name));

      if (!cupsMakeServerCredentials(tls_keypath, hostname[0] ? hostname : tls_common_name, 0, NULL, time(NULL) + 365 * 86400))
      {
	DEBUG_puts("4_httpTLSStart: cupsMakeServerCredentials failed.");
	http->error  = errno = EINVAL;
	http->status = HTTP_STATUS_ERROR;
	_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1);

	return (-1);
      }
    }

    DEBUG_printf(("4_httpTLSStart: Using certificate \"%s\" and private key \"%s\".", crtfile, keyfile));

    status = gnutls_certificate_set_x509_key_file(*credentials, crtfile, keyfile, GNUTLS_X509_FMT_PEM);
  }

  if (!status)
    status = gnutls_credentials_set(http->tls, GNUTLS_CRD_CERTIFICATE, *credentials);

  if (status)
  {
    http->error  = EIO;
    http->status = HTTP_STATUS_ERROR;

    DEBUG_printf(("4_httpTLSStart: Unable to complete client/server setup: %s", gnutls_strerror(status)));
    _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0);

    gnutls_deinit(http->tls);
    gnutls_certificate_free_credentials(*credentials);
    free(credentials);
    http->tls = NULL;

    return (-1);
  }

  strlcpy(priority_string, "NORMAL", sizeof(priority_string));

  if (tls_options & _HTTP_TLS_DENY_TLS10)
    strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-TLS1.0:-VERS-SSL3.0", sizeof(priority_string));
  else if (tls_options & _HTTP_TLS_ALLOW_SSL3)
    strlcat(priority_string, ":+VERS-TLS-ALL", sizeof(priority_string));
  else
    strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-SSL3.0", sizeof(priority_string));

  if (!(tls_options & _HTTP_TLS_ALLOW_RC4))
    strlcat(priority_string, ":-ARCFOUR-128", sizeof(priority_string));

  if (!(tls_options & _HTTP_TLS_ALLOW_DH))
    strlcat(priority_string, ":!ANON-DH", sizeof(priority_string));

#ifdef HAVE_GNUTLS_PRIORITY_SET_DIRECT
  gnutls_priority_set_direct(http->tls, priority_string, NULL);

#else
  gnutls_priority_t priority;		/* Priority */

  gnutls_priority_init(&priority, priority_string, NULL);
  gnutls_priority_set(http->tls, priority);
  gnutls_priority_deinit(priority);
#endif /* HAVE_GNUTLS_PRIORITY_SET_DIRECT */

  gnutls_transport_set_ptr(http->tls, (gnutls_transport_ptr_t)http);
  gnutls_transport_set_pull_function(http->tls, http_gnutls_read);
#ifdef HAVE_GNUTLS_TRANSPORT_SET_PULL_TIMEOUT_FUNCTION
  gnutls_transport_set_pull_timeout_function(http->tls, (gnutls_pull_timeout_func)httpWait);
#endif /* HAVE_GNUTLS_TRANSPORT_SET_PULL_TIMEOUT_FUNCTION */
  gnutls_transport_set_push_function(http->tls, http_gnutls_write);

  while ((status = gnutls_handshake(http->tls)) != GNUTLS_E_SUCCESS)
  {
    DEBUG_printf(("5_httpStartTLS: gnutls_handshake returned %d (%s)",
                  status, gnutls_strerror(status)));

    if (gnutls_error_is_fatal(status))
    {
      http->error  = EIO;
      http->status = HTTP_STATUS_ERROR;

      _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0);

      gnutls_deinit(http->tls);
      gnutls_certificate_free_credentials(*credentials);
      free(credentials);
      http->tls = NULL;

      return (-1);
    }
  }

  http->tls_credentials = credentials;

  return (0);
}
Example #16
0
bool TlsSocket::Start()
{
#ifdef HAVE_LIBGNUTLS
	gnutls_certificate_credentials_t cred;
	m_retCode = gnutls_certificate_allocate_credentials(&cred);
	if (m_retCode != 0)
	{
		ReportError("Could not create TLS context");
		return false;
	}

	m_context = cred;

	if (m_certFile && m_keyFile)
	{
		m_retCode = gnutls_certificate_set_x509_key_file((gnutls_certificate_credentials_t)m_context,
			m_certFile, m_keyFile, GNUTLS_X509_FMT_PEM);
		if (m_retCode != 0)
		{
			ReportError("Could not load certificate or key file");
			Close();
			return false;
		}
	}

	gnutls_session_t sess;
	m_retCode = gnutls_init(&sess, m_isClient ? GNUTLS_CLIENT : GNUTLS_SERVER);
	if (m_retCode != 0)
	{
		ReportError("Could not create TLS session");
		Close();
		return false;
	}

	m_session = sess;

	m_initialized = true;

	const char* priority = !m_cipher.Empty() ? m_cipher.Str() : "NORMAL";

	m_retCode = gnutls_priority_set_direct((gnutls_session_t)m_session, priority, nullptr);
	if (m_retCode != 0)
	{
		ReportError("Could not select cipher for TLS");
		Close();
		return false;
	}

	if (m_host)
	{
		m_retCode = gnutls_server_name_set((gnutls_session_t)m_session, GNUTLS_NAME_DNS, m_host, m_host.Length());
		if (m_retCode != 0)
		{
			ReportError("Could not set host name for TLS");
			Close();
			return false;
		}
	}

	m_retCode = gnutls_credentials_set((gnutls_session_t)m_session, GNUTLS_CRD_CERTIFICATE,
		(gnutls_certificate_credentials_t*)m_context);
	if (m_retCode != 0)
	{
		ReportError("Could not initialize TLS session");
		Close();
		return false;
	}

	gnutls_transport_set_ptr((gnutls_session_t)m_session, (gnutls_transport_ptr_t)(size_t)m_socket);

	m_retCode = gnutls_handshake((gnutls_session_t)m_session);
	if (m_retCode != 0)
	{
		ReportError("TLS handshake failed");
		Close();
		return false;
	}

	m_connected = true;
	return true;
#endif /* HAVE_LIBGNUTLS */

#ifdef HAVE_OPENSSL
	m_context = SSL_CTX_new(SSLv23_method());

	if (!m_context)
	{
		ReportError("Could not create TLS context");
		return false;
	}

	if (m_certFile && m_keyFile)
	{
		if (SSL_CTX_use_certificate_chain_file((SSL_CTX*)m_context, m_certFile) != 1)
		{
			ReportError("Could not load certificate file");
			Close();
			return false;
		}
		if (SSL_CTX_use_PrivateKey_file((SSL_CTX*)m_context, m_keyFile, SSL_FILETYPE_PEM) != 1)
		{
			ReportError("Could not load key file");
			Close();
			return false;
		}
	}

	m_session = SSL_new((SSL_CTX*)m_context);
	if (!m_session)
	{
		ReportError("Could not create TLS session");
		Close();
		return false;
	}

	if (!m_cipher.Empty() && !SSL_set_cipher_list((SSL*)m_session, m_cipher))
	{
		ReportError("Could not select cipher for TLS");
		Close();
		return false;
	}

	if (m_host && !SSL_set_tlsext_host_name((SSL*)m_session, m_host))
	{
		ReportError("Could not set host name for TLS");
		Close();
		return false;
	}

	if (!SSL_set_fd((SSL*)m_session, m_socket))
	{
		ReportError("Could not set the file descriptor for TLS");
		Close();
		return false;
	}

	int error_code = m_isClient ? SSL_connect((SSL*)m_session) : SSL_accept((SSL*)m_session);
	if (error_code < 1)
	{
		ReportError("TLS handshake failed");
		Close();
		return false;
	}

	m_connected = true;
	return true;
#endif /* HAVE_OPENSSL */
}
Example #17
0
int ssl_open(http_t *client, char *msg)
{
	int ret;
	char buf[256];
	size_t len;
	const char *sn, *err;
	const gnutls_datum_t *cert_list;
	unsigned int cert_list_size = 0;
	gnutls_x509_crt_t cert;

	if (!client->ssl_enabled)
		return tcp_init(&client->tcp, msg);

	/* Initialize TLS session */
	logit(LOG_INFO, "%s, initiating HTTPS ...", msg);
	gnutls_init(&client->ssl, GNUTLS_CLIENT);

	/* SSL SNI support: tell the servername we want to speak to */
	http_get_remote_name(client, &sn);
	gnutls_session_set_ptr(client->ssl, (void *)sn);
	if (gnutls_server_name_set(client->ssl, GNUTLS_NAME_DNS, sn, strlen(sn)))
		return RC_HTTPS_SNI_ERROR;

	/* Use default priorities */
	ret = gnutls_priority_set_direct(client->ssl, "NORMAL", &err);
	if (ret < 0) {
		if (ret == GNUTLS_E_INVALID_REQUEST)
			logit(LOG_ERR, "Syntax error at: %s", err);

		return RC_HTTPS_INVALID_REQUEST;
	}

	/* put the x509 credentials to the current session */
	gnutls_credentials_set(client->ssl, GNUTLS_CRD_CERTIFICATE, xcred);

	/* connect to the peer */
	tcp_set_port(&client->tcp, HTTPS_DEFAULT_PORT);
	DO(tcp_init(&client->tcp, msg));

	/* Forward TCP socket to GnuTLS, the set_int() API is perhaps too new still ... since 3.1.9 */
//	gnutls_transport_set_int(client->ssl, client->tcp.ip.socket);
	gnutls_transport_set_ptr(client->ssl, (gnutls_transport_ptr_t)(intptr_t)client->tcp.ip.socket);

	/* Perform the TLS handshake, ignore non-fatal errors. */
	do {
		ret = gnutls_handshake(client->ssl);
	}
	while (ret != 0 && !gnutls_error_is_fatal(ret));

	if (gnutls_error_is_fatal(ret)) {
		logit(LOG_ERR, "SSL handshake with %s failed: %s", sn, gnutls_strerror(ret));
		return RC_HTTPS_FAILED_CONNECT;
	}

	ssl_get_info(client);

	/* Get server's certificate (note: beware of dynamic allocation) - opt */
	cert_list = gnutls_certificate_get_peers(client->ssl, &cert_list_size);
	if (cert_list_size > 0) {
		if (gnutls_x509_crt_init(&cert))
			return RC_HTTPS_FAILED_GETTING_CERT;

		gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);

		len = sizeof(buf);
		gnutls_x509_crt_get_dn(cert, buf, &len);
		logit(LOG_INFO, "SSL server cert subject: %s", buf);

		len = sizeof(buf);
		gnutls_x509_crt_get_issuer_dn(cert, buf, &len);
		logit(LOG_INFO, "SSL server cert issuer: %s", buf);

		gnutls_x509_crt_deinit(cert);
	}

	return 0;
}
Example #18
0
mref_err_t mref_fetch_handle(struct mref *m, FILE *h, const char *me) {
    char *mhsh, *rhsh, *store;
    gnutls_session_t sess;
    gnutls_anon_client_credentials_t cred;
    int fd = fileno(h);
    int err, i, store_good;
    unsigned char h_mref[32], h_calc[32];
    gcry_md_hd_t ghd;
    size_t mhsh_len, ns_len, rhsh_len, store_len;

    if (!mref_split(m)) return MREF_ERR_NOT_FIELDS;

    store = mref_field_alloc(m, MREF_FLD_STORE);
    if (!store) return MREF_ERR_NOMEM;
    //printf("store is: %s\n", store);

    mhsh = mref_field_alloc(m, MREF_FLD_MESSAGE_HASH);
    if (!mhsh) return MREF_ERR_NOMEM;
    _mref_b64dec(h_mref, mhsh, mref_field_length(m, MREF_FLD_MESSAGE_HASH));
    //printf("mhsh is: %s\n", mhsh);

    rhsh = mref_field_alloc(m, MREF_FLD_MREF_HASH);
    rhsh_len = mref_field_length(m, MREF_FLD_MREF_HASH);
    if (!rhsh) return MREF_ERR_NOMEM;
    //printf("rhsh is: %s\n", rhsh);

    /*
       err = gnutls_global_init();
       if (err != GNUTLS_E_SUCCESS) return MREF_ERR_TLS(err);
       err = gnutls_init(&sess, GNUTLS_CLIENT);
       if (err != GNUTLS_E_SUCCESS) return MREF_ERR_TLS(err);
       err = gnutls_credentials_set(sess, GNUTLS_CRD_ANON, &cred);
       if (err != GNUTLS_E_SUCCESS) return MREF_ERR_TLS(err);
       */

    /*** from info gnutls ***/

    {
        int ret, sd;
        gnutls_session_t session;
        char buffer[MAX_BUF + 1];
        const char *err;

        /* Initialize TLS session
        */
        gnutls_init (&session, GNUTLS_CLIENT);

        gnutls_session_set_ptr (session, (void *) store);

        gnutls_server_name_set (session, GNUTLS_NAME_DNS, store, strlen(store));

        /* Use default priorities */
        ret = gnutls_priority_set_direct (session, "NORMAL", &err);
        if (ret < 0)
        {
            if (ret == GNUTLS_E_INVALID_REQUEST)
            {
                fprintf (stderr, "Syntax error at: %s\n", err);
            }
            exit (1);
        }

        /* put the x509 credentials to the current session
        */
        gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, mref_cred());

        /* connect to the peer
        */
        sd = tcp_connect(store);
        if (sd == -1) {
            gnutls_deinit (session);
            return MREF_ERR_CONNECT_FAIL;
        }

        gnutls_transport_set_int (session, sd);
        gnutls_handshake_set_timeout (session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);

        /* Perform the TLS handshake
        */
        do
            ret = gnutls_handshake (session);
        while (ret < 0 && gnutls_error_is_fatal (ret) == 0);

        if (ret < 0) {
            tcp_close(sd);
            gnutls_deinit(session);
            return MREF_ERR_TLS(ret);
        }

        gnutls_record_send (session, rhsh, rhsh_len);
        //fprintf(stderr, "sent rhsh, %d bytes\n", rhsh_len);

        mref_trace_headers(m, h, sd, me);

        state = st_goodbad;
        ns_len = 0;
        gcry_md_open(&ghd, GCRY_MD_SHA256, 0);
        if (!ghd) return MREF_ERR_GCRYPT;

        while ((ret = gnutls_record_recv (session, buffer, MAX_BUF)) > 0) {
            int i;
            for (i = 0; i < ret; ++i) {

                switch (state) {
                    case st_goodbad:
                        store_good = buffer[i] == '+';
                        ++state;
                        break;
                    case st_count:
                        if (buffer[i] >= '0' && buffer[i] <= '9')
                            ns_len = ns_len * 10 + buffer[i] - '0';
                        else if (buffer[i] == ':') ++state;
                        else return MREF_ERR_STORE_PROTO;
                        break;
                    case st_data:
                        if (store_good) fputc(buffer[i], h);
                        else fputc(buffer[i], stderr);
                        gcry_md_write(ghd, buffer + i, 1);
                        if (--ns_len == 0) ++ state;
                        break;
                    case st_comma:
                        if (buffer[i] == ',') break;
                    case st_toomuch:
                        return MREF_ERR_STORE_PROTO;
                }
            }
        }
        if (ret < 0) {
           if (gnutls_error_is_fatal(ret)) {
               fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret));
           } else {
               fprintf (stderr, "*** Warning: %s\n", gnutls_strerror (ret));
               gnutls_bye (session, GNUTLS_SHUT_RDWR);
           }
           tcp_close(sd);
           gnutls_deinit (session);
           return MREF_ERR_TLS(ret);
        }

        tcp_close(sd);
        gnutls_deinit (session);

        memcpy(h_calc, gcry_md_read(ghd, 0), 32);
        gcry_md_close(ghd);

        if (memcmp(h_mref, h_calc, 32) != 0) return MREF_ERR_BAD_MSG_HASH;

        if (fflush(h) != 0) return MREF_ERR_SYS;
        if (fsync(fd) != 0) return MREF_ERR_SYS;
        fclose(h); /* cannot fail */

        return 0;
    }
}
Example #19
0
int main(int argc, char **argv)
{
	int ret;
	int i;
	gnutls_session_t state;
	char portname[6];
	socket_st hd;
	char app_proto[32] = "";

	cmd_parser(argc, argv);

#ifndef _WIN32
	signal(SIGPIPE, SIG_IGN);
#endif

	sockets_init();

	if (gnutls_global_init() < 0) {
		fprintf(stderr, "global state initialization error\n");
		exit(1);
	}

	gnutls_global_set_log_function(tls_log_func);
	gnutls_global_set_log_level(debug);

	/* get server name */
	snprintf(portname, sizeof(portname), "%d", port);

	/* X509 stuff */
	if (gnutls_certificate_allocate_credentials(&xcred) < 0) {	/* space for 2 certificates */
		fprintf(stderr, "memory error\n");
		exit(1);
	}

	/* SRP stuff */
#ifdef ENABLE_SRP
	if (gnutls_srp_allocate_client_credentials(&srp_cred) < 0) {
		fprintf(stderr, "memory error\n");
		exit(1);
	}
#endif

#ifdef ENABLE_ANON
	/* ANON stuff */
	if (gnutls_anon_allocate_client_credentials(&anon_cred) < 0) {
		fprintf(stderr, "memory error\n");
		exit(1);
	}
#endif

	if (HAVE_OPT(STARTTLS_PROTO)) {
		snprintf(app_proto, sizeof(app_proto), "%s", OPT_ARG(STARTTLS_PROTO));
	}

	if (app_proto[0] == 0) {
		snprintf(app_proto, sizeof(app_proto), "%s", port_to_service(portname, "tcp"));
	}

	sockets_init();

	i = 0;

	printf("GnuTLS debug client %s\n", gnutls_check_version(NULL));
	printf("Checking %s:%s\n", hostname, portname);
	do {

		if (tls_tests[i].test_name == NULL)
			break;	/* finished */

		/* if neither of SSL3 and TLSv1 are supported, exit
		 */
		if (i > 6 && tls1_2_ok == 0 && tls1_1_ok == 0 && tls1_ok == 0
		    && ssl3_ok == 0) {
			fprintf(stderr,
				"\nServer does not support any of SSL 3.0, TLS 1.0 and TLS 1.1 and TLS 1.2\n");
			break;
		}

		socket_open(&hd, hostname, portname, 0, NULL);
		hd.verbose = verbose;

		socket_starttls(&hd, app_proto);

		gnutls_init(&state, GNUTLS_CLIENT | GNUTLS_NO_EXTENSIONS);

		gnutls_transport_set_ptr(state, (gnutls_transport_ptr_t)
					 gl_fd_to_handle(hd.fd));
		set_read_funcs(state);
		if (hostname && is_ip(hostname) == 0)
			gnutls_server_name_set(state, GNUTLS_NAME_DNS,
					       hostname, strlen(hostname));

		do {
			if (strcmp(app_proto, "https") != 0 && tls_tests[i].https_only != 0) {
				i++;
				break;
			}

			ret = tls_tests[i].func(state);

			if (ret != TEST_IGNORE) {
				printf("%58s...", tls_tests[i].test_name);
				fflush(stdout);
			}

			if (ret == TEST_SUCCEED) {
				if (tls_tests[i].suc_str == NULL)
					printf(" %s\n", ext_text);
				else
					printf(" %s\n", tls_tests[i].suc_str);
			} else if (ret == TEST_FAILED)
				printf(" %s\n", tls_tests[i].fail_str);
			else if (ret == TEST_UNSURE)
				printf(" %s\n", tls_tests[i].unsure_str);
			else if (ret == TEST_IGNORE) {
				if (tls_tests[i+1].test_name)
					i++;
				else
					break;
			}
		}
		while (ret == TEST_IGNORE
		       && tls_tests[i].test_name != NULL);

		gnutls_deinit(state);

		socket_bye(&hd);

		i++;
	}
	while (1);

#ifdef ENABLE_SRP
	gnutls_srp_free_client_credentials(srp_cred);
#endif
	gnutls_certificate_free_credentials(xcred);
#ifdef ENABLE_ANON
	gnutls_anon_free_client_credentials(anon_cred);
#endif
	gnutls_global_deinit();

	return 0;
}
Example #20
0
/* initializes a gnutls_session_t with some defaults.
 */
static gnutls_session_t
init_tls_session (const char *hostname)
{
  const char *err;

  gnutls_session_t session;

  gnutls_init (&session, GNUTLS_CLIENT);

  if (gnutls_priority_set_direct (session, info.priorities, &err) < 0)
    {
      fprintf (stderr, "Syntax error at: %s\n", err);
      exit (1);
    }

  /* allow the use of private ciphersuites.
   */
  if (disable_extensions == 0)
    {
      gnutls_handshake_set_private_extensions (session, 1);
      gnutls_server_name_set (session, GNUTLS_NAME_DNS, hostname,
			      strlen (hostname));
      if (cert_type_priority[0])
	gnutls_certificate_type_set_priority (session, cert_type_priority);
    }

  if (cipher_priority[0])
    gnutls_cipher_set_priority (session, cipher_priority);
  if (comp_priority[0])
    gnutls_compression_set_priority (session, comp_priority);
  if (kx_priority[0])
    gnutls_kx_set_priority (session, kx_priority);
  if (protocol_priority[0])
    gnutls_protocol_set_priority (session, protocol_priority);
  if (mac_priority[0])
    gnutls_mac_set_priority (session, mac_priority);

  gnutls_dh_set_prime_bits (session, 512);

  gnutls_credentials_set (session, GNUTLS_CRD_ANON, anon_cred);
  if (srp_cred)
    gnutls_credentials_set (session, GNUTLS_CRD_SRP, srp_cred);
  if (psk_cred)
    gnutls_credentials_set (session, GNUTLS_CRD_PSK, psk_cred);
  gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred);

  gnutls_certificate_client_set_retrieve_function (xcred, cert_callback);
  gnutls_certificate_set_verify_function (xcred, cert_verify_callback);
  gnutls_certificate_set_verify_flags (xcred, 0);

  /* send the fingerprint */
#ifdef ENABLE_OPENPGP
  if (fingerprint != 0)
    gnutls_openpgp_send_cert (session, GNUTLS_OPENPGP_CERT_FINGERPRINT);
#endif

  /* use the max record size extension */
  if (record_max_size > 0 && disable_extensions == 0)
    {
      if (gnutls_record_set_max_size (session, record_max_size) < 0)
	{
	  fprintf (stderr,
		   "Cannot set the maximum record size to %d.\n",
		   record_max_size);
	  fprintf (stderr, "Possible values: 512, 1024, 2048, 4096.\n");
	  exit (1);
	}
    }

#ifdef ENABLE_OPRFI
  if (info.opaque_prf_input)
    gnutls_oprfi_enable_client (session, strlen (info.opaque_prf_input),
				info.opaque_prf_input);
#endif

#ifdef ENABLE_SESSION_TICKET
  if (!info.noticket)
    gnutls_session_ticket_enable_client (session);
#endif

  return session;
}
Example #21
0
int main(void)
{
        int ret, sd, ii;
        gnutls_session_t session;
        char buffer[MAX_BUF + 1];
        const char *err;
        gnutls_certificate_credentials_t xcred;

        if (gnutls_check_version("3.1.4") == NULL) {
                fprintf(stderr, "GnuTLS 3.1.4 or later is required for this example\n");
                exit(1);
        }

        /* for backwards compatibility with gnutls < 3.3.0 */
        gnutls_global_init();

        /* X509 stuff */
        gnutls_certificate_allocate_credentials(&xcred);

        /* sets the trusted cas file
         */
        gnutls_certificate_set_x509_trust_file(xcred, CAFILE,
                                               GNUTLS_X509_FMT_PEM);
        gnutls_certificate_set_verify_function(xcred,
                                               _verify_certificate_callback);

        /* If client holds a certificate it can be set using the following:
         *
         gnutls_certificate_set_x509_key_file (xcred, 
         "cert.pem", "key.pem", 
         GNUTLS_X509_FMT_PEM); 
         */

        /* Initialize TLS session 
         */
        gnutls_init(&session, GNUTLS_CLIENT);

        gnutls_session_set_ptr(session, (void *) "my_host_name");

        gnutls_server_name_set(session, GNUTLS_NAME_DNS, "my_host_name",
                               strlen("my_host_name"));

        /* use default priorities */
        gnutls_set_default_priority(session);
#if 0
	/* if more fine-graned control is required */
        ret = gnutls_priority_set_direct(session, 
                                         "NORMAL", &err);
        if (ret < 0) {
                if (ret == GNUTLS_E_INVALID_REQUEST) {
                        fprintf(stderr, "Syntax error at: %s\n", err);
                }
                exit(1);
        }
#endif

        /* put the x509 credentials to the current session
         */
        gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);

        /* connect to the peer
         */
        sd = tcp_connect();

        gnutls_transport_set_int(session, sd);
        gnutls_handshake_set_timeout(session,
                                     GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);

        /* Perform the TLS handshake
         */
        do {
                ret = gnutls_handshake(session);
        }
        while (ret < 0 && gnutls_error_is_fatal(ret) == 0);

        if (ret < 0) {
                fprintf(stderr, "*** Handshake failed\n");
                gnutls_perror(ret);
                goto end;
        } else {
                char *desc;

                desc = gnutls_session_get_desc(session);
                printf("- Session info: %s\n", desc);
                gnutls_free(desc);
        }

        gnutls_record_send(session, MSG, strlen(MSG));

        ret = gnutls_record_recv(session, buffer, MAX_BUF);
        if (ret == 0) {
                printf("- Peer has closed the TLS connection\n");
                goto end;
        } else if (ret < 0 && gnutls_error_is_fatal(ret) == 0) {
                fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret));
        } else if (ret < 0) {
                fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret));
                goto end;
        }

        if (ret > 0) {
                printf("- Received %d bytes: ", ret);
                for (ii = 0; ii < ret; ii++) {
                        fputc(buffer[ii], stdout);
                }
                fputs("\n", stdout);
        }

        gnutls_bye(session, GNUTLS_SHUT_RDWR);

      end:

        tcp_close(sd);

        gnutls_deinit(session);

        gnutls_certificate_free_credentials(xcred);

        gnutls_global_deinit();

        return 0;
}
Example #22
0
File: ssl.c Project: ezc/elinks
int
init_ssl_connection(struct socket *socket,
		    const unsigned char *server_name)
{
#ifdef USE_OPENSSL
	socket->ssl = SSL_new(context);
	if (!socket->ssl) return S_SSL_ERROR;

	if (!SSL_set_ex_data(socket->ssl, socket_SSL_ex_data_idx, socket)) {
		SSL_free(socket->ssl);
		socket->ssl = NULL;
		return S_SSL_ERROR;
	}

	/* If the server name is known, pass it to OpenSSL.
	 *
	 * The return value of SSL_set_tlsext_host_name is not
	 * documented.  The source shows that it returns 1 if
	 * successful; on error, it calls SSLerr and returns 0.  */
	if (server_name
	    && !SSL_set_tlsext_host_name(socket->ssl, server_name)) {
		SSL_free(socket->ssl);
		socket->ssl = NULL;
		return S_SSL_ERROR;
	}

#elif defined(CONFIG_GNUTLS)
	ssl_t *state = mem_alloc(sizeof(ssl_t));

	if (!state) return S_SSL_ERROR;

	if (gnutls_init(state, GNUTLS_CLIENT) < 0) {
		/* DBG("sslinit %s", gnutls_strerror(ret)); */
		mem_free(state);
		return S_SSL_ERROR;
	}

	if (gnutls_cred_set(*state, GNUTLS_CRD_ANON, anon_cred) < 0) {
		/* DBG("sslanoncred %s", gnutls_strerror(ret)); */
		gnutls_deinit(*state);
		mem_free(state);
		return S_SSL_ERROR;
	}

	if (gnutls_cred_set(*state, GNUTLS_CRD_CERTIFICATE, xcred) < 0) {
		/* DBG("sslx509cred %s", gnutls_strerror(ret)); */
		gnutls_deinit(*state);
		mem_free(state);
		return S_SSL_ERROR;
	}

#ifdef HAVE_GNUTLS_PRIORITY_SET_DIRECT
	/* Disable OpenPGP certificates because they are not widely
	 * used and ELinks does not yet support verifying them.
	 * Besides, in GnuTLS < 2.4.0, they require the gnutls-extra
	 * library, whose GPLv3+ is not compatible with GPLv2 of
	 * ELinks.
	 *
	 * Disable TLS1.1 because https://bugzilla.novell.com/ does
	 * not reply to it and leaves the connection open so that
	 * ELinks does not detect an SSL error but rather times out.
	 * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=528661#25
	 *
	 * There is another gnutls_priority_set_direct call elsewhere
	 * in ELinks.  If you change the priorities here, please check
	 * whether that one needs to be changed as well.  */
	if (gnutls_priority_set_direct(*state,
				       "NORMAL:-CTYPE-OPENPGP:-VERS-TLS1.1",
				       NULL)) {
		gnutls_deinit(*state);
		mem_free(state);
		return S_SSL_ERROR;
	}
#else
	gnutls_set_default_priority(*state);
#endif
#if 0
	/* Deprecated functions */
	/* gnutls_handshake_set_private_extensions(*state, 1); */
	gnutls_cipher_set_priority(*state, cipher_priority);
	gnutls_kx_set_priority(*state, kx_priority);
	/* gnutls_certificate_type_set_priority(*state, cert_type_priority); */
#endif

	if (server_name
	    && gnutls_server_name_set(*state, GNUTLS_NAME_DNS, server_name,
				      strlen(server_name))) {
		gnutls_deinit(*state);
		mem_free(state);
		return S_SSL_ERROR;
	}

	socket->ssl = state;
#endif

	return S_OK;
}
Example #23
0
static CURLcode
gtls_connect_step1(struct connectdata *conn,
                   int sockindex)
{
  struct SessionHandle *data = conn->data;
  gnutls_session_t session;
  int rc;
  void *ssl_sessionid;
  size_t ssl_idsize;
  bool sni = TRUE; /* default is SNI enabled */
#ifdef ENABLE_IPV6
  struct in6_addr addr;
#else
  struct in_addr addr;
#endif
#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
  static const int cipher_priority[] = {
  /* These two ciphers were added to GnuTLS as late as ver. 3.0.1,
     but this code path is only ever used for ver. < 2.12.0.
     GNUTLS_CIPHER_AES_128_GCM,
     GNUTLS_CIPHER_AES_256_GCM,
  */
    GNUTLS_CIPHER_AES_128_CBC,
    GNUTLS_CIPHER_AES_256_CBC,
    GNUTLS_CIPHER_CAMELLIA_128_CBC,
    GNUTLS_CIPHER_CAMELLIA_256_CBC,
    GNUTLS_CIPHER_3DES_CBC,
  };
  static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
  static int protocol_priority[] = { 0, 0, 0, 0 };
#else
#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
/* If GnuTLS was compiled without support for SRP it will error out if SRP is
   requested in the priority string, so treat it specially
 */
#define GNUTLS_SRP "+SRP"
  const char* prioritylist;
  const char *err = NULL;
#endif

  if(conn->ssl[sockindex].state == ssl_connection_complete)
    /* to make us tolerant against being called more than once for the
       same connection */
    return CURLE_OK;

  if(!gtls_inited)
    Curl_gtls_init();

  /* GnuTLS only supports SSLv3 and TLSv1 */
  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
    failf(data, "GnuTLS does not support SSLv2");
    return CURLE_SSL_CONNECT_ERROR;
  }
  else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
    sni = FALSE; /* SSLv3 has no SNI */

  /* allocate a cred struct */
  rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
  if(rc != GNUTLS_E_SUCCESS) {
    failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
    return CURLE_SSL_CONNECT_ERROR;
  }

#ifdef USE_TLS_SRP
  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
    infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);

    rc = gnutls_srp_allocate_client_credentials(
           &conn->ssl[sockindex].srp_client_cred);
    if(rc != GNUTLS_E_SUCCESS) {
      failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
            gnutls_strerror(rc));
      return CURLE_OUT_OF_MEMORY;
    }

    rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
                                           srp_client_cred,
                                           data->set.ssl.username,
                                           data->set.ssl.password);
    if(rc != GNUTLS_E_SUCCESS) {
      failf(data, "gnutls_srp_set_client_cred() failed: %s",
            gnutls_strerror(rc));
      return CURLE_BAD_FUNCTION_ARGUMENT;
    }
  }
#endif

  if(data->set.ssl.CAfile) {
    /* set the trusted CA cert bundle file */
    gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);

    rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
                                                data->set.ssl.CAfile,
                                                GNUTLS_X509_FMT_PEM);
    if(rc < 0) {
      infof(data, "error reading ca cert file %s (%s)\n",
            data->set.ssl.CAfile, gnutls_strerror(rc));
      if(data->set.ssl.verifypeer)
        return CURLE_SSL_CACERT_BADFILE;
    }
    else
      infof(data, "found %d certificates in %s\n",
            rc, data->set.ssl.CAfile);
  }

#ifdef HAS_CAPATH
  if(data->set.ssl.CApath) {
    /* set the trusted CA cert directory */
    rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
                                                data->set.ssl.CApath,
                                                GNUTLS_X509_FMT_PEM);
    if(rc < 0) {
      infof(data, "error reading ca cert file %s (%s)\n",
            data->set.ssl.CAfile, gnutls_strerror(rc));
      if(data->set.ssl.verifypeer)
        return CURLE_SSL_CACERT_BADFILE;
    }
    else
      infof(data, "found %d certificates in %s\n",
            rc, data->set.ssl.CApath);
  }
#endif

#ifdef CURL_CA_FALLBACK
  /* use system ca certificate store as fallback */
  if(data->set.ssl.verifypeer &&
     !(data->set.ssl.CAfile || data->set.ssl.CApath)) {
    gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred);
  }
#endif

  if(data->set.ssl.CRLfile) {
    /* set the CRL list file */
    rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
                                              data->set.ssl.CRLfile,
                                              GNUTLS_X509_FMT_PEM);
    if(rc < 0) {
      failf(data, "error reading crl file %s (%s)",
            data->set.ssl.CRLfile, gnutls_strerror(rc));
      return CURLE_SSL_CRL_BADFILE;
    }
    else
      infof(data, "found %d CRL in %s\n",
            rc, data->set.ssl.CRLfile);
  }

  /* Initialize TLS session as a client */
  rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
  if(rc != GNUTLS_E_SUCCESS) {
    failf(data, "gnutls_init() failed: %d", rc);
    return CURLE_SSL_CONNECT_ERROR;
  }

  /* convenient assign */
  session = conn->ssl[sockindex].session;

  if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
#ifdef ENABLE_IPV6
     (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
#endif
     sni &&
     (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
                             strlen(conn->host.name)) < 0))
    infof(data, "WARNING: failed to configure server name indication (SNI) "
          "TLS extension\n");

  /* Use default priorities */
  rc = gnutls_set_default_priority(session);
  if(rc != GNUTLS_E_SUCCESS)
    return CURLE_SSL_CONNECT_ERROR;

#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
  rc = gnutls_cipher_set_priority(session, cipher_priority);
  if(rc != GNUTLS_E_SUCCESS)
    return CURLE_SSL_CONNECT_ERROR;

  /* Sets the priority on the certificate types supported by gnutls. Priority
   is higher for types specified before others. After specifying the types
   you want, you must append a 0. */
  rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
  if(rc != GNUTLS_E_SUCCESS)
    return CURLE_SSL_CONNECT_ERROR;

  if(data->set.ssl.cipher_list != NULL) {
    failf(data, "can't pass a custom cipher list to older GnuTLS"
          " versions");
    return CURLE_SSL_CONNECT_ERROR;
  }

  switch (data->set.ssl.version) {
    case CURL_SSLVERSION_SSLv3:
      protocol_priority[0] = GNUTLS_SSL3;
      break;
    case CURL_SSLVERSION_DEFAULT:
    case CURL_SSLVERSION_TLSv1:
      protocol_priority[0] = GNUTLS_TLS1_0;
      protocol_priority[1] = GNUTLS_TLS1_1;
      protocol_priority[2] = GNUTLS_TLS1_2;
      break;
    case CURL_SSLVERSION_TLSv1_0:
      protocol_priority[0] = GNUTLS_TLS1_0;
      break;
    case CURL_SSLVERSION_TLSv1_1:
      protocol_priority[0] = GNUTLS_TLS1_1;
      break;
    case CURL_SSLVERSION_TLSv1_2:
      protocol_priority[0] = GNUTLS_TLS1_2;
    break;
      case CURL_SSLVERSION_SSLv2:
    default:
      failf(data, "GnuTLS does not support SSLv2");
      return CURLE_SSL_CONNECT_ERROR;
      break;
  }
  rc = gnutls_protocol_set_priority(session, protocol_priority);
  if(rc != GNUTLS_E_SUCCESS) {
    failf(data, "Did you pass a valid GnuTLS cipher list?");
    return CURLE_SSL_CONNECT_ERROR;
  }

#else
  /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
   * removed if a run-time error indicates that SRP is not supported by this
   * GnuTLS version */
  switch (data->set.ssl.version) {
    case CURL_SSLVERSION_SSLv3:
      prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
      sni = false;
      break;
    case CURL_SSLVERSION_DEFAULT:
    case CURL_SSLVERSION_TLSv1:
      prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
      break;
    case CURL_SSLVERSION_TLSv1_0:
      prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
                     "+VERS-TLS1.0:" GNUTLS_SRP;
      break;
    case CURL_SSLVERSION_TLSv1_1:
      prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
                     "+VERS-TLS1.1:" GNUTLS_SRP;
      break;
    case CURL_SSLVERSION_TLSv1_2:
      prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
                     "+VERS-TLS1.2:" GNUTLS_SRP;
      break;
    case CURL_SSLVERSION_SSLv2:
    default:
      failf(data, "GnuTLS does not support SSLv2");
      return CURLE_SSL_CONNECT_ERROR;
      break;
  }
  rc = gnutls_priority_set_direct(session, prioritylist, &err);
  if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
    if(!strcmp(err, GNUTLS_SRP)) {
      /* This GnuTLS was probably compiled without support for SRP.
       * Note that fact and try again without it. */
      int validprioritylen = curlx_uztosi(err - prioritylist);
      char *prioritycopy = strdup(prioritylist);
      if(!prioritycopy)
        return CURLE_OUT_OF_MEMORY;

      infof(data, "This GnuTLS does not support SRP\n");
      if(validprioritylen)
        /* Remove the :+SRP */
        prioritycopy[validprioritylen - 1] = 0;
      rc = gnutls_priority_set_direct(session, prioritycopy, &err);
      free(prioritycopy);
    }
  }
  if(rc != GNUTLS_E_SUCCESS) {
    failf(data, "Error %d setting GnuTLS cipher list starting with %s",
          rc, err);
    return CURLE_SSL_CONNECT_ERROR;
  }
#endif

#ifdef HAS_ALPN
  if(data->set.ssl_enable_alpn) {
    int cur = 0;
    gnutls_datum_t protocols[2];

#ifdef USE_NGHTTP2
    if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
      protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
      protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
      cur++;
      infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
    }
#endif

    protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
    protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
    cur++;
    infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);

    gnutls_alpn_set_protocols(session, protocols, cur, 0);
  }
#endif

  if(data->set.str[STRING_CERT]) {
    if(data->set.str[STRING_KEY_PASSWD]) {
#if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
      const unsigned int supported_key_encryption_algorithms =
        GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
        GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
        GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
        GNUTLS_PKCS_USE_PBES2_AES_256;
      rc = gnutls_certificate_set_x509_key_file2(
           conn->ssl[sockindex].cred,
           data->set.str[STRING_CERT],
           data->set.str[STRING_KEY] ?
           data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
           do_file_type(data->set.str[STRING_CERT_TYPE]),
           data->set.str[STRING_KEY_PASSWD],
           supported_key_encryption_algorithms);
      if(rc != GNUTLS_E_SUCCESS) {
        failf(data,
              "error reading X.509 potentially-encrypted key file: %s",
              gnutls_strerror(rc));
        return CURLE_SSL_CONNECT_ERROR;
      }
#else
      failf(data, "gnutls lacks support for encrypted key files");
      return CURLE_SSL_CONNECT_ERROR;
#endif
    }
    else {
      rc = gnutls_certificate_set_x509_key_file(
           conn->ssl[sockindex].cred,
           data->set.str[STRING_CERT],
           data->set.str[STRING_KEY] ?
           data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
           do_file_type(data->set.str[STRING_CERT_TYPE]) );
      if(rc != GNUTLS_E_SUCCESS) {
        failf(data, "error reading X.509 key or certificate file: %s",
              gnutls_strerror(rc));
        return CURLE_SSL_CONNECT_ERROR;
      }
    }
  }

#ifdef USE_TLS_SRP
  /* put the credentials to the current session */
  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
    rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
                                conn->ssl[sockindex].srp_client_cred);
    if(rc != GNUTLS_E_SUCCESS) {
      failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
      return CURLE_SSL_CONNECT_ERROR;
    }
  }
  else
#endif
  {
    rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
                                conn->ssl[sockindex].cred);
    if(rc != GNUTLS_E_SUCCESS) {
      failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
      return CURLE_SSL_CONNECT_ERROR;
    }
  }

  /* set the connection handle (file descriptor for the socket) */
  gnutls_transport_set_ptr(session,
                           GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));

  /* register callback functions to send and receive data. */
  gnutls_transport_set_push_function(session, Curl_gtls_push);
  gnutls_transport_set_pull_function(session, Curl_gtls_pull);

  /* lowat must be set to zero when using custom push and pull functions. */
  gnutls_transport_set_lowat(session, 0);

#ifdef HAS_OCSP
  if(data->set.ssl.verifystatus) {
    rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
    if(rc != GNUTLS_E_SUCCESS) {
      failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
      return CURLE_SSL_CONNECT_ERROR;
    }
  }
#endif

  /* This might be a reconnect, so we check for a session ID in the cache
     to speed up things */

  if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
    /* we got a session id, use it! */
    gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);

    /* Informational message */
    infof (data, "SSL re-using session ID\n");
  }

  return CURLE_OK;
}
Example #24
0
static int tls_open(URLContext *h, const char *uri, int flags)
{
    TLSContext *c = h->priv_data;
    int ret;
    int port;
    const char *p;
    char buf[200], host[200], opts[50] = "";
    int numerichost = 0;
    struct addrinfo hints = { 0 }, *ai = NULL;
    const char *proxy_path;
    int use_proxy;

    if ((ret = ff_tls_init()) < 0)
        return ret;

    if (c->listen)
        snprintf(opts, sizeof(opts), "?listen=1");

    av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0, uri);

    p = strchr(uri, '?');

    if (!p) {
        p = opts;
    } else {
        if (av_find_info_tag(opts, sizeof(opts), "listen", p))
            c->listen = 1;
    }

    ff_url_join(buf, sizeof(buf), "tcp", NULL, host, port, "%s", p);

    hints.ai_flags = AI_NUMERICHOST;
    if (!getaddrinfo(host, NULL, &hints, &ai)) {
        numerichost = 1;
        freeaddrinfo(ai);
    }

    proxy_path = getenv("http_proxy");
    use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), host) &&
                proxy_path && av_strstart(proxy_path, "http://", NULL);

    if (use_proxy) {
        char proxy_host[200], proxy_auth[200], dest[200];
        int proxy_port;
        av_url_split(NULL, 0, proxy_auth, sizeof(proxy_auth),
                     proxy_host, sizeof(proxy_host), &proxy_port, NULL, 0,
                     proxy_path);
        ff_url_join(dest, sizeof(dest), NULL, NULL, host, port, NULL);
        ff_url_join(buf, sizeof(buf), "httpproxy", proxy_auth, proxy_host,
                    proxy_port, "/%s", dest);
    }

    ret = ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE,
                     &h->interrupt_callback, NULL);
    if (ret)
        goto fail;
    c->fd = ffurl_get_file_handle(c->tcp);

#if CONFIG_GNUTLS
    gnutls_init(&c->session, c->listen ? GNUTLS_SERVER : GNUTLS_CLIENT);
    if (!c->listen && !numerichost)
        gnutls_server_name_set(c->session, GNUTLS_NAME_DNS, host, strlen(host));
    gnutls_certificate_allocate_credentials(&c->cred);
    set_options(h, uri);
    if (c->ca_file) {
        ret = gnutls_certificate_set_x509_trust_file(c->cred, c->ca_file, GNUTLS_X509_FMT_PEM);
        if (ret < 0)
            av_log(h, AV_LOG_ERROR, "%s\n", gnutls_strerror(ret));
    }
#if GNUTLS_VERSION_MAJOR >= 3
    else
        gnutls_certificate_set_x509_system_trust(c->cred);
#endif
    gnutls_certificate_set_verify_flags(c->cred, c->verify ?
                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT : 0);
    if (c->cert_file && c->key_file) {
        ret = gnutls_certificate_set_x509_key_file(c->cred,
                                                   c->cert_file, c->key_file,
                                                   GNUTLS_X509_FMT_PEM);
        if (ret < 0) {
            av_log(h, AV_LOG_ERROR,
                   "Unable to set cert/key files %s and %s: %s\n",
                   c->cert_file, c->key_file, gnutls_strerror(ret));
            ret = AVERROR(EIO);
            goto fail;
        }
    } else if (c->cert_file || c->key_file)
        av_log(h, AV_LOG_ERROR, "cert and key required\n");
    gnutls_credentials_set(c->session, GNUTLS_CRD_CERTIFICATE, c->cred);
    gnutls_transport_set_ptr(c->session, (gnutls_transport_ptr_t)
                                         (intptr_t) c->fd);
    gnutls_priority_set_direct(c->session, "NORMAL", NULL);
    while (1) {
        ret = gnutls_handshake(c->session);
        if (ret == 0)
            break;
        if ((ret = do_tls_poll(h, ret)) < 0)
            goto fail;
    }
    if (c->verify) {
        unsigned int status, cert_list_size;
        gnutls_x509_crt_t cert;
        const gnutls_datum_t *cert_list;
        if ((ret = gnutls_certificate_verify_peers2(c->session, &status)) < 0) {
            av_log(h, AV_LOG_ERROR, "Unable to verify peer certificate: %s\n",
                                    gnutls_strerror(ret));
            ret = AVERROR(EIO);
            goto fail;
        }
        if (status & GNUTLS_CERT_INVALID) {
            av_log(h, AV_LOG_ERROR, "Peer certificate failed verification\n");
            ret = AVERROR(EIO);
            goto fail;
        }
        if (gnutls_certificate_type_get(c->session) != GNUTLS_CRT_X509) {
            av_log(h, AV_LOG_ERROR, "Unsupported certificate type\n");
            ret = AVERROR(EIO);
            goto fail;
        }
        gnutls_x509_crt_init(&cert);
        cert_list = gnutls_certificate_get_peers(c->session, &cert_list_size);
        gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER);
        ret = gnutls_x509_crt_check_hostname(cert, host);
        gnutls_x509_crt_deinit(cert);
        if (!ret) {
            av_log(h, AV_LOG_ERROR,
                   "The certificate's owner does not match hostname %s\n", host);
            ret = AVERROR(EIO);
            goto fail;
        }
    }
#elif CONFIG_OPENSSL
    c->ctx = SSL_CTX_new(c->listen ? TLSv1_server_method() : TLSv1_client_method());
    if (!c->ctx) {
        av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
        ret = AVERROR(EIO);
        goto fail;
    }
    set_options(h, uri);
    if (c->ca_file) {
        if (!SSL_CTX_load_verify_locations(c->ctx, c->ca_file, NULL))
            av_log(h, AV_LOG_ERROR, "SSL_CTX_load_verify_locations %s\n", ERR_error_string(ERR_get_error(), NULL));
    }
    if (c->cert_file && !SSL_CTX_use_certificate_chain_file(c->ctx, c->cert_file)) {
        av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n",
               c->cert_file, ERR_error_string(ERR_get_error(), NULL));
        ret = AVERROR(EIO);
        goto fail;
    }
    if (c->key_file && !SSL_CTX_use_PrivateKey_file(c->ctx, c->key_file, SSL_FILETYPE_PEM)) {
        av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n",
               c->key_file, ERR_error_string(ERR_get_error(), NULL));
        ret = AVERROR(EIO);
        goto fail;
    }
    // Note, this doesn't check that the peer certificate actually matches
    // the requested hostname.
    if (c->verify)
        SSL_CTX_set_verify(c->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
    c->ssl = SSL_new(c->ctx);
    if (!c->ssl) {
        av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
        ret = AVERROR(EIO);
        goto fail;
    }
    SSL_set_fd(c->ssl, c->fd);
    if (!c->listen && !numerichost)
        SSL_set_tlsext_host_name(c->ssl, host);
    while (1) {
        ret = c->listen ? SSL_accept(c->ssl) : SSL_connect(c->ssl);
        if (ret > 0)
            break;
        if (ret == 0) {
            av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n");
            ret = AVERROR(EIO);
            goto fail;
        }
        if ((ret = do_tls_poll(h, ret)) < 0)
            goto fail;
    }
#endif
    return 0;
fail:
    TLS_free(c);
    if (c->tcp)
        ffurl_close(c->tcp);
    ff_tls_deinit();
    return ret;
}
Example #25
0
void
test_cli_serv(gnutls_certificate_credentials_t server_cred, const char *prio,
              const gnutls_datum_t *ca_cert, const char *host)
{
	int exit_code = EXIT_SUCCESS;
	int ret;
	/* Server stuff. */
	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;

	/* General init. */
	reset_buffers();

	/* Init server */

	gnutls_init(&server, GNUTLS_SERVER);
	gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
			       server_cred);
	gnutls_priority_set_direct(server, prio, NULL);
	gnutls_transport_set_push_function(server, server_push);
	gnutls_transport_set_pull_function(server, server_pull);
	gnutls_transport_set_ptr(server, server);

	/* Init client */
	ret = gnutls_certificate_allocate_credentials(&clientx509cred);
	if (ret < 0)
		exit(1);

	ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, ca_cert, GNUTLS_X509_FMT_PEM);
	if (ret < 0)
		exit(1);

	ret = gnutls_init(&client, GNUTLS_CLIENT);
	if (ret < 0)
		exit(1);


	assert(gnutls_server_name_set(client, GNUTLS_NAME_DNS, host, strlen(host))>=0);

	ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
			       clientx509cred);
	if (ret < 0)
		exit(1);

	gnutls_priority_set_direct(client, prio, NULL);
	gnutls_transport_set_push_function(client, client_push);
	gnutls_transport_set_pull_function(client, client_pull);
	gnutls_transport_set_ptr(client, client);

	HANDSHAKE(client, server);

	/* check the number of certificates received and verify */
	{
		gnutls_typed_vdata_st data[2];
		unsigned status;

		memset(data, 0, sizeof(data));

		data[0].type = GNUTLS_DT_DNS_HOSTNAME;
		data[0].data = (void*)host;

		data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
		data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER;

		ret = gnutls_certificate_verify_peers(client, data, 2, &status);
		if (ret < 0) {
			fail("could not verify certificate: %s\n", gnutls_strerror(ret));
			exit(1);
		}

		if (status != 0) {
			gnutls_datum_t t;
			assert(gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509, &t, 0)>=0);
			fail("could not verify certificate for '%s': %.4x: %s\n", host, status, t.data);
			gnutls_free(t.data);
			exit(1);
		}

		/* check gnutls_certificate_verify_peers3 */
		ret = gnutls_certificate_verify_peers3(client, host, &status);
		if (ret < 0) {
			fail("could not verify certificate: %s\n", gnutls_strerror(ret));
			exit(1);
		}

		if (status != 0) {
			gnutls_datum_t t;
			assert(gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509, &t, 0)>=0);
			fail("could not verify certificate3: %.4x: %s\n", status, t.data);
			gnutls_free(t.data);
			exit(1);
		}
	}

	gnutls_bye(client, GNUTLS_SHUT_RDWR);
	gnutls_bye(server, GNUTLS_SHUT_RDWR);

	gnutls_deinit(client);
	gnutls_deinit(server);

	gnutls_certificate_free_credentials(clientx509cred);

	if (debug > 0) {
		if (exit_code == 0)
			puts("Self-test successful");
		else
			puts("Self-test failed");
	}
}
Example #26
0
extern int xlibgnutls_dtls_handshake(gnutls_session_t *session, int udp_sd, unsigned verbose_level) {
	const char *CAFILE = "ca-cert.pem"; // TODO: use anoncred
	int ret;
	const char *err;

	if (gnutls_check_version("3.1.4") == NULL) {
		print_error("GnuTLS 3.1.4 or later is required");
		return -1;
	}

	/* for backwards compatibility with gnutls < 3.3.0 */
	gnutls_global_init();

	if (verbose_level >= VERBOSE_LEVEL_GNUTLS) {
		gnutls_global_set_log_level(9999);
		gnutls_global_set_log_function(gnutls_log);
	}

	/* X509 stuff */
	gnutls_certificate_allocate_credentials(&xcred);

	/* sets the trusted cas file */
	gnutls_certificate_set_x509_trust_file(xcred, CAFILE, GNUTLS_X509_FMT_PEM);
	gnutls_certificate_set_verify_function(xcred, verify_certificate_callback);

	/* Initialize TLS session */
	gnutls_init(session, GNUTLS_CLIENT | GNUTLS_DATAGRAM);

	/* put the x509 credentials to the current session */
	gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE, xcred);
	gnutls_server_name_set(*session, GNUTLS_NAME_DNS, "my_host_name", strlen("my_host_name"));

	if (verbose_level >= VERBOSE_LEVEL_PACKETS) {
		gnutls_transport_set_push_function(*session, gnutls_push_func_custom);
		//gnutls_transport_set_pull_function(*session, gnutls_pull_func_custom);
		//gnutls_transport_set_pull_timeout_function(*session, gnutls_pull_timeout_func_custom);
	}

	gnutls_dtls_set_mtu(*session, 1 << 14);
	gnutls_set_default_priority(*session);
	/* if more fine-graned control is required */
	ret = gnutls_priority_set_direct(*session, "NORMAL", &err);
	if (ret < 0) {
		if (ret == GNUTLS_E_INVALID_REQUEST)
			print_error("syntax error at: %d", err);
		goto end;
	}

	gnutls_transport_set_int(*session, udp_sd);
	gnutls_handshake_set_timeout(*session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);

	if (verbose_level >= VERBOSE_LEVEL_CLIENT)
		print_info("handshake started");
	do {
		ret = gnutls_handshake(*session);
	}
	while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
	/* Note that DTLS may also receive GNUTLS_E_LARGE_PACKET */
	if (verbose_level >= VERBOSE_LEVEL_CLIENT)
		print_info("handshake finished");

	if (ret < 0) {
		print_error("handshake failed with return code %d", ret);
		gnutls_perror(ret);
		goto end;
	} else {
		char *desc;
		desc = gnutls_session_get_desc(*session);
		if (verbose_level >= VERBOSE_LEVEL_CLIENT)
			print_info("session info: %s", desc);
		gnutls_free(desc);
	}

	ret = 0;

end:
	return ret;
}
Example #27
0
static void client(int fd)
{
	int ret;
	gnutls_certificate_credentials_t x509_cred;
	gnutls_session_t session;

	global_init();

	if (debug) {
		gnutls_global_set_log_function(client_log_func);
		gnutls_global_set_log_level(7);
	}

	gnutls_certificate_allocate_credentials(&x509_cred);

	/* Initialize TLS session
	 */
	gnutls_init(&session, GNUTLS_CLIENT|GNUTLS_DATAGRAM);
	gnutls_handshake_set_timeout(session, 20 * 1000);

	assert(gnutls_priority_set_direct(session, "NORMAL:-VERS-ALL:+VERS-DTLS1.2", NULL)>= 0);

	gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);

	gnutls_transport_set_int(session, fd);
	assert(gnutls_server_name_set(session, GNUTLS_NAME_DNS, HOSTNAME, strlen(HOSTNAME))>=0);

	/* Perform the TLS handshake
	 */
	do {
		ret = gnutls_handshake(session);
	}
	while (ret < 0 && gnutls_error_is_fatal(ret) == 0);

	if (ret == GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM) {
		/* success */
		goto end;
	}

	if (ret < 0) {
		fail("client: Handshake failed: %s\n", gnutls_strerror(ret));
	} else {
		if (debug)
			success("client: Handshake was completed\n");
	}

	if (debug)
		success("client: TLS version is: %s\n",
			gnutls_protocol_get_name
			(gnutls_protocol_get_version(session)));

	gnutls_bye(session, GNUTLS_SHUT_WR);

      end:

	close(fd);

	gnutls_deinit(session);

	gnutls_certificate_free_credentials(x509_cred);

	gnutls_global_deinit();
}
Example #28
0
static Ecore_Con_Ssl_Error
_ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr)
{
   const gnutls_datum_t *cert_list;
   unsigned int iter, cert_list_size;
   gnutls_x509_crt_t cert = NULL;
   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 (svr->ssl_state)
     {
      case ECORE_CON_SSL_STATE_DONE:
        return ECORE_CON_SSL_ERROR_NONE;

      case ECORE_CON_SSL_STATE_INIT:
        if (svr->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */
          return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;

        switch (svr->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;
          }

        SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&svr->session, GNUTLS_CLIENT));
        SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_client(svr->session));
        SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_server_name_set(svr->session, GNUTLS_NAME_DNS, svr->name, strlen(svr->name)));
        INF("Applying priority string: %s", priority);
        SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(svr->session, priority, NULL));
        SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_CERTIFICATE, svr->cert));
        // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_PSK, svr->pskcred_c));
        if (!svr->use_cert)
          SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_ANON, svr->anoncred_c));

        gnutls_dh_set_prime_bits(svr->session, 512);
        gnutls_transport_set_ptr(svr->session, (gnutls_transport_ptr_t)((intptr_t)svr->fd));
        svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;

      case ECORE_CON_SSL_STATE_HANDSHAKING:
        if (!svr->session)
          {
             DBG("Server was previously lost, going to error condition");
             goto error;
          }
        ret = gnutls_handshake(svr->session);
        DBG("calling gnutls_handshake(): returned with '%s'", gnutls_strerror_name(ret));
        SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret));
        if (!ret)
          {
             svr->handshaking = EINA_FALSE;
             svr->ssl_state = ECORE_CON_SSL_STATE_DONE;
          }
        else
          {
             if (gnutls_record_get_direction(svr->session))
               ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
             else
               ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
             return ECORE_CON_SSL_ERROR_NONE;
          }

      default:
        break;
     }

   if (!svr->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(svr->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(svr->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(svr->session, &cert_list_size)));
   SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size);

   SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert));
   SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER));

   SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, svr->name));
   gnutls_x509_crt_deinit(cert);
   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(svr->session)));
   if (svr->session && (svr->ssl_state != ECORE_CON_SSL_STATE_DONE))
     {
        ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(svr->session)));
        ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(svr->session)));
     }
   if (cert)
     gnutls_x509_crt_deinit(cert);
   _ecore_con_ssl_server_shutdown_gnutls(svr);
   return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
}
Example #29
0
int main(void)
{
        int ret, sd, ii;
        gnutls_session_t session;
        char buffer[MAX_BUF + 1];
        const char *err;
        gnutls_certificate_credentials_t xcred;

        if (gnutls_check_version("3.1.4") == NULL) {
                fprintf(stderr, "GnuTLS 3.1.4 or later is required for this example\n");
                exit(1);
        }

        /* for backwards compatibility with gnutls < 3.3.0 */
        gnutls_global_init();

        /* X509 stuff */
        gnutls_certificate_allocate_credentials(&xcred);

        /* sets the trusted cas file */
        gnutls_certificate_set_x509_trust_file(xcred, CAFILE,
                                               GNUTLS_X509_FMT_PEM);
        gnutls_certificate_set_verify_function(xcred,
                                               verify_certificate_callback);

        /* Initialize TLS session */
        gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_DATAGRAM);

        /* Use default priorities */
        ret = gnutls_priority_set_direct(session, 
                                         "NORMAL", &err);
        if (ret < 0) {
                if (ret == GNUTLS_E_INVALID_REQUEST) {
                        fprintf(stderr, "Syntax error at: %s\n", err);
                }
                exit(1);
        }

        /* put the x509 credentials to the current session */
        gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
        gnutls_server_name_set(session, GNUTLS_NAME_DNS, "my_host_name",
                               strlen("my_host_name"));

        /* connect to the peer */
        sd = udp_connect();

        gnutls_transport_set_int(session, sd);

        /* set the connection MTU */
        gnutls_dtls_set_mtu(session, 1000);
        gnutls_handshake_set_timeout(session,
                                     GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);

        /* Perform the TLS handshake */
        do {
                ret = gnutls_handshake(session);
        }
        while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
        /* Note that DTLS may also receive GNUTLS_E_LARGE_PACKET */

        if (ret < 0) {
                fprintf(stderr, "*** Handshake failed\n");
                gnutls_perror(ret);
                goto end;
        } else {
                char *desc;

                desc = gnutls_session_get_desc(session);
                printf("- Session info: %s\n", desc);
                gnutls_free(desc);
        }

        gnutls_record_send(session, MSG, strlen(MSG));

        ret = gnutls_record_recv(session, buffer, MAX_BUF);
        if (ret == 0) {
                printf("- Peer has closed the TLS connection\n");
                goto end;
        } else if (ret < 0 && gnutls_error_is_fatal(ret) == 0) {
                fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret));
        } else if (ret < 0) {
                fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret));
                goto end;
        }

        if (ret > 0) {
                printf("- Received %d bytes: ", ret);
                for (ii = 0; ii < ret; ii++) {
                        fputc(buffer[ii], stdout);
                }
                fputs("\n", stdout);
        }

        /* It is suggested not to use GNUTLS_SHUT_RDWR in DTLS
         * connections because the peer's closure message might
         * be lost */
        gnutls_bye(session, GNUTLS_SHUT_WR);

      end:

        udp_close(sd);

        gnutls_deinit(session);

        gnutls_certificate_free_credentials(xcred);

        gnutls_global_deinit();

        return 0;
}
rfbNewClientAction upgradeNewClientToTls (_rfbClientRec* cl) {
	//Eine SSL Session beginnen
	gnutls_session_t session = 0;
	gnutls_certificate_credentials_t credentials = 0;
	gnutls_datum_t data;
	int gtlsRet = GNUTLS_E_SUCCESS;
	std::cout<<"New Client Connection, upgrade protocol to Tls"<<std::endl;
	try {
		//Zertifikat
		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_certificate_allocate_credentials(&credentials))) {
			std::cerr << "failed to allocate credentials." << std::endl;
			throw std::runtime_error("failed to allocate credentials.");
		}

		data.size = g_caCertificate.size();
		data.data = (unsigned char*) g_caCertificate.data();
		gnutls_certificate_set_x509_trust_mem(credentials, &data, GNUTLS_X509_FMT_PEM);

		// Verifizierung des Zertifikats in der übergebenen Callback Funktion, Ausführung erfolgt als Teil des Handshakes
		gnutls_certificate_set_verify_function(credentials, [] (gnutls_session_t session) throw () -> int {
			std::cout << "verifying certificate...";
			//Server Zertifikat prüfen:
			unsigned int verify = 0;
			if (GNUTLS_E_SUCCESS != gnutls_certificate_verify_peers3(session, (const char*) gnutls_session_get_ptr(session), &verify)) {
				std::cerr << "certficate verification failed." << std::endl;
				return -1;
			}
			if (verify != 0) {
				gnutls_datum_t pr;
				std::cout << "no" << std::endl;
				gnutls_certificate_verification_status_print(verify, GNUTLS_CRT_X509, &pr, 0);
				std::cerr << pr.data << std::endl;
				free(pr.data);
				return -2;
			}
			std::cout << "yes" << std::endl;
			return 0;
		});
		//Session
		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_init(&session, GNUTLS_CLIENT))) {
			std::cerr << "failed to init session." << std::endl;
			throw std::runtime_error("failed to init session.");
		}

		gnutls_server_name_set(session, GNUTLS_NAME_DNS, g_peerHostName.data(), g_peerHostName.length());
		gnutls_session_set_ptr(session, (void*) g_peerHostName.c_str());

		if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_priority_set_direct(session, CIPHERSUITE_PRIORITIES, 0))) {
			std::cerr << "failed to set priority." << std::endl;
			throw std::runtime_error("failed to set priority.");
		}

		gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, credentials);
		gnutls_transport_set_int(session, cl->sock);
		gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
		if (GNUTLS_E_SUCCESS != ((gtlsRet = gnutls_handshake(session)))) {
			std::cerr << "handshake failed." << std::endl;
			throw std::runtime_error("handshake failed.");
		}

		//Ciphersuite 
		std::cout << "ciphersuite: " << gnutls_cipher_suite_get_name(gnutls_kx_get(session), gnutls_cipher_get(session), gnutls_mac_get(session)) << std::endl;

		//Send password, which was received in answer of webserver
		if ((gtlsRet = gnutls_record_send(session, (void*)g_serverPassword.data(), g_serverPassword.size())) <= 0) {
			std::cerr << "Sending Password failed." << std::endl;
			throw std::runtime_error("Sending Password failed.");
		}

		rfbssl_ctx* ctx = (rfbssl_ctx*) malloc(sizeof(struct rfbssl_ctx));
		ctx->peeklen = 0;
		ctx->peekstart = 0;
		ctx->session = session;
		ctx->x509_cred = credentials;
		ctx->dh_params = 0;
		
		cl->sslctx = (rfbSslCtx*)ctx;
	} catch (...) {
		//Irgendein Fehler trat auf, dann schließen.
		std::cerr << gtlsRet << ' ' << gnutls_error_is_fatal(gtlsRet) << std::endl;
		std::cerr << gnutls_strerror(gtlsRet) << std::endl;
		std::cerr << gnutls_alert_get_name(gnutls_alert_get(session)) << std::endl;
		if (session) gnutls_deinit(session);
		if (credentials) gnutls_certificate_free_credentials(credentials);
		
		return RFB_CLIENT_REFUSE;
	}
	
	return RFB_CLIENT_ACCEPT;
}