Exemple #1
0
bool
ssl_connect_wget (int fd)
{
  static const int cert_type_priority[] = {
    GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0
  };
  struct wgnutls_transport_context *ctx;
  gnutls_session session;
  int err;
  int allowed_protocols[4] = {0, 0, 0, 0};
  gnutls_init (&session, GNUTLS_CLIENT);
  gnutls_set_default_priority (session);
  gnutls_certificate_type_set_priority (session, cert_type_priority);
  gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
#ifndef FD_TO_SOCKET
# define FD_TO_SOCKET(X) (X)
#endif
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr) FD_TO_SOCKET (fd));

  err = 0;
  switch (opt.secure_protocol)
    {
    case secure_protocol_auto:
      break;
    case secure_protocol_sslv2:
    case secure_protocol_sslv3:
      allowed_protocols[0] = GNUTLS_SSL3;
      err = gnutls_protocol_set_priority (session, allowed_protocols);
      break;
    case secure_protocol_tlsv1:
      allowed_protocols[0] = GNUTLS_TLS1_0;
      allowed_protocols[1] = GNUTLS_TLS1_1;
      allowed_protocols[2] = GNUTLS_TLS1_2;
      err = gnutls_protocol_set_priority (session, allowed_protocols);
      break;
    default:
      abort ();
    }
  if (err < 0)
    {
      logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
      gnutls_deinit (session);
      return false;
    }

  err = gnutls_handshake (session);
  if (err < 0)
    {
      logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
      gnutls_deinit (session);
      return false;
    }

  ctx = xnew0 (struct wgnutls_transport_context);
  ctx->session = session;
  fd_register_transport (fd, &wgnutls_transport, ctx);
  return true;
}
Exemple #2
0
static int vnc_set_gnutls_priority(gnutls_session_t s, int x509)
{
    static const int cert_types[] = { GNUTLS_CRT_X509, 0 };
    static const int protocols[] = {
        GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0
    };
    static const int kx_anon[] = { GNUTLS_KX_ANON_DH, 0 };
    static const int kx_x509[] = {
        GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA,
        GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0
    };
    int rc;

    rc = gnutls_kx_set_priority(s, x509 ? kx_x509 : kx_anon);
    if (rc != GNUTLS_E_SUCCESS) {
        return -1;
    }

    rc = gnutls_certificate_type_set_priority(s, cert_types);
    if (rc != GNUTLS_E_SUCCESS) {
        return -1;
    }

    rc = gnutls_protocol_set_priority(s, protocols);
    if (rc != GNUTLS_E_SUCCESS) {
        return -1;
    }
    return 0;
}
Exemple #3
0
struct tls_connection * tls_connection_init(void *ssl_ctx)
{
	struct tls_connection *conn;
	const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
	const int protos[2] = { GNUTLS_TLS1, 0 };


	conn = malloc(sizeof(*conn));
	if (conn == NULL)
		return NULL;
	memset(conn, 0, sizeof(*conn));
	if (gnutls_init(&conn->session, GNUTLS_CLIENT) < 0) {
		wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
			   "connection");
		free(conn);
		return NULL;
	}

	gnutls_set_default_priority(conn->session);
	gnutls_certificate_type_set_priority(conn->session, cert_types);
	gnutls_protocol_set_priority(conn->session, protos);

	gnutls_transport_set_pull_function(conn->session, tls_pull_func);
	gnutls_transport_set_push_function(conn->session, tls_push_func);
	gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);

	gnutls_certificate_allocate_credentials(&conn->xcred);

	return conn;
}
Exemple #4
0
static void
ADD_PROTOCOL (gnutls_session session, int protocol)
{
  static int _proto_priority[] = { 0, 0 };
  _proto_priority[0] = protocol;

  gnutls_protocol_set_priority (session, _proto_priority);
}
Exemple #5
0
static int
tls_handshake (struct ikstls_data **datap, ikstransport *trans, void *sock)
{
	const int protocol_priority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
	const int kx_priority[] = { GNUTLS_KX_RSA, 0 };
	const int cipher_priority[] = { GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0};
	const int comp_priority[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
	const int mac_priority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
	struct ikstls_data *data;
	int ret;

	*datap = NULL;

	data = iks_malloc (sizeof(*data));
	if (!data) return IKS_NOMEM;
	memset (data, 0, sizeof(*data));
	data->trans = trans;
	data->sock = sock;
	data->timeout = -1;

	if (gnutls_global_init () != 0) {
		iks_free (data);
		return IKS_NOMEM;
	}

	if (gnutls_certificate_allocate_credentials (&data->cred) < 0) {
		iks_free (data);
		return IKS_NOMEM;
	}

	if (gnutls_init (&data->sess, GNUTLS_CLIENT) != 0) {
		gnutls_certificate_free_credentials (data->cred);
		iks_free (data);
		return IKS_NOMEM;
	}

	gnutls_protocol_set_priority (data->sess, protocol_priority);
	gnutls_cipher_set_priority(data->sess, cipher_priority);
	gnutls_compression_set_priority(data->sess, comp_priority);
	gnutls_kx_set_priority(data->sess, kx_priority);
	gnutls_mac_set_priority(data->sess, mac_priority);
	gnutls_credentials_set (data->sess, GNUTLS_CRD_CERTIFICATE, data->cred);

	gnutls_transport_set_push_function (data->sess, (gnutls_push_func) tls_push);
	gnutls_transport_set_pull_function (data->sess, (gnutls_pull_func) tls_pull);
	gnutls_transport_set_ptr (data->sess, data);

	ret = gnutls_handshake (data->sess);
	if (ret != 0) {
		gnutls_deinit (data->sess);
		gnutls_certificate_free_credentials (data->cred);
		iks_free (data);
		return IKS_NET_TLSFAIL;
	}

	*datap = data;
	return IKS_OK;
}
Exemple #6
0
int
SSL_accept (SSL * ssl)
{
  X509_STORE_CTX *store;
  int cert_list_size = 0;
  int err;
  int i, j;
  int x_priority[GNUTLS_MAX_ALGORITHM_NUM];
  /* take options into account before accepting */

  memset (x_priority, 0, sizeof (x_priority));
  if (ssl->options & SSL_OP_NO_TLSv1)
    {
      for (i = 0, j = 0;
	   i < GNUTLS_MAX_ALGORITHM_NUM && x_priority[i] != 0; i++, j++)
	{
	  if (ssl->ctx->method->protocol_priority[j] == GNUTLS_TLS1)
	    j++;
	  else
	    x_priority[i] = ssl->ctx->method->protocol_priority[j];
	}
      if (i < GNUTLS_MAX_ALGORITHM_NUM)
	x_priority[i] = 0;
      gnutls_protocol_set_priority (ssl->gnutls_state,
				    ssl->ctx->method->protocol_priority);
    }

  /* FIXME: dh params, do we want client cert? */

  err = gnutls_handshake (ssl->gnutls_state);
  ssl->last_error = err;

  if (err < 0)
    {
      last_error = err;
      return 0;
    }

  store = (X509_STORE_CTX *) calloc (1, sizeof (X509_STORE_CTX));
  store->ssl = ssl;
  store->cert_list = gnutls_certificate_get_peers (ssl->gnutls_state,
						   &cert_list_size);

  if (ssl->verify_callback)
    {
      ssl->verify_callback (1 /*FIXME*/, store);
    }
  ssl->state = SSL_ST_OK;

  err = store->error;
  free (store);

  /* FIXME: deal with error from callback */

  return 1;
}
Exemple #7
0
static void
ADD_PROTOCOL3 (gnutls_session session, int p1, int p2, int p3)
{
  static int _proto_priority[] = { 0, 0, 0, 0 };
  _proto_priority[0] = p1;
  _proto_priority[1] = p2;
  _proto_priority[2] = p3;

  gnutls_protocol_set_priority (session, _proto_priority);
}
static int tls_gnutls_init_session(struct tls_global *global,
				   struct tls_connection *conn)
{
#if LIBGNUTLS_VERSION_NUMBER >= 0x020200
	const char *err;
#else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
	const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
	const int protos[2] = { GNUTLS_TLS1, 0 };
#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */
	int ret;

	ret = gnutls_init(&conn->session,
			  global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
	if (ret < 0) {
		wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
			   "connection: %s", gnutls_strerror(ret));
		return -1;
	}

	ret = gnutls_set_default_priority(conn->session);
	if (ret < 0)
		goto fail;

#if LIBGNUTLS_VERSION_NUMBER >= 0x020200
	ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0",
					 &err);
	if (ret < 0) {
		wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at "
			   "'%s'", err);
		goto fail;
	}
#else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
	ret = gnutls_certificate_type_set_priority(conn->session, cert_types);
	if (ret < 0)
		goto fail;

	ret = gnutls_protocol_set_priority(conn->session, protos);
	if (ret < 0)
		goto fail;
#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */

	gnutls_transport_set_pull_function(conn->session, tls_pull_func);
	gnutls_transport_set_push_function(conn->session, tls_push_func);
	gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);

	return 0;

fail:
	wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
		   gnutls_strerror(ret));
	gnutls_deinit(conn->session);
	return -1;
}
Exemple #9
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;
}
Exemple #10
0
static int
handshake (struct stream_data *data)
{
	const int protocol_priority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
	const int kx_priority[] = { GNUTLS_KX_RSA, 0 };
	const int cipher_priority[] = { GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0};
	const int comp_priority[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
	const int mac_priority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
	int ret;

#ifndef WIN32
	gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
#endif

	if (gnutls_global_init () != 0)
		return IKS_NOMEM;

	if (gnutls_certificate_allocate_credentials (&data->cred) < 0)
		return IKS_NOMEM;

	if (gnutls_init (&data->sess, GNUTLS_CLIENT) != 0) {
		gnutls_certificate_free_credentials (data->cred);
		return IKS_NOMEM;
	}
	gnutls_protocol_set_priority (data->sess, protocol_priority);
	gnutls_cipher_set_priority(data->sess, cipher_priority);
	gnutls_compression_set_priority(data->sess, comp_priority);
	gnutls_kx_set_priority(data->sess, kx_priority);
	gnutls_mac_set_priority(data->sess, mac_priority);
	gnutls_credentials_set (data->sess, GNUTLS_CRD_CERTIFICATE, data->cred);


	gnutls_transport_set_push_function (data->sess, (gnutls_push_func) tls_push);
	gnutls_transport_set_pull_function (data->sess, (gnutls_pull_func) tls_pull);
	
	gnutls_transport_set_ptr (data->sess, data->prs);

	ret = gnutls_handshake (data->sess);
	if (ret != 0) {
		gnutls_deinit (data->sess);
		gnutls_certificate_free_credentials (data->cred);
		return IKS_NET_TLSFAIL;
	}

	data->flags &= (~SF_TRY_SECURE);
	data->flags |= SF_SECURE;

	iks_send_header (data->prs, data->server);

	return IKS_OK;
} // HAVE_GNUTLS
Exemple #11
0
SSL *
SSL_new (SSL_CTX * ctx)
{
  SSL *ssl;
  int err;

  ssl = (SSL *) calloc (1, sizeof (SSL));
  if (!ssl)
    return NULL;

  err = gnutls_certificate_allocate_credentials (&ssl->gnutls_cred);
  if (err < 0)
    {
      last_error = err;
      free (ssl);
      return NULL;
    }

  gnutls_init (&ssl->gnutls_state, ctx->method->connend);

  gnutls_protocol_set_priority (ssl->gnutls_state,
				ctx->method->protocol_priority);
  gnutls_cipher_set_priority (ssl->gnutls_state,
			      ctx->method->cipher_priority);
  gnutls_compression_set_priority (ssl->gnutls_state,
				   ctx->method->comp_priority);
  gnutls_kx_set_priority (ssl->gnutls_state, ctx->method->kx_priority);
  gnutls_mac_set_priority (ssl->gnutls_state, ctx->method->mac_priority);

  gnutls_credentials_set (ssl->gnutls_state, GNUTLS_CRD_CERTIFICATE,
			  ssl->gnutls_cred);
  if (ctx->certfile)
    gnutls_certificate_set_x509_trust_file (ssl->gnutls_cred,
					    ctx->certfile,
					    ctx->certfile_type);
  if (ctx->keyfile)
    gnutls_certificate_set_x509_key_file (ssl->gnutls_cred,
					  ctx->certfile, ctx->keyfile,
					  ctx->keyfile_type);
  ssl->ctx = ctx;
  ssl->verify_mode = ctx->verify_mode;
  ssl->verify_callback = ctx->verify_callback;

  ssl->options = ctx->options;

  ssl->rfd = (gnutls_transport_ptr_t) - 1;
  ssl->wfd = (gnutls_transport_ptr_t) - 1;

  return ssl;
}
Exemple #12
0
static gnutls_session initialize_state(void)
{
	gnutls_session session;

	gnutls_init(&session, GNUTLS_SERVER);

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

	gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
	return session;
}
  bool GnuTLSClientAnon::init( const std::string&,
                               const std::string&,
                               const StringList& )
  {
    if( m_initLib && gnutls_global_init() != 0 )
      return false;

    if( gnutls_anon_allocate_client_credentials( &m_anoncred ) < 0 )
      return false;

    if( gnutls_init( m_session, GNUTLS_CLIENT ) != 0 )
      return false;

#if GNUTLS_VERSION_NUMBER >= 0x020600
    int ret = gnutls_priority_set_direct( *m_session, "SECURE128:+PFS:+COMP-ALL:+VERS-TLS-ALL:-VERS-SSL3.0:+SIGN-ALL:+CURVE-ALL", 0 );
    if( ret != GNUTLS_E_SUCCESS )
      return false;
#else
    const int protocolPriority[] = {
#ifdef GNUTLS_TLS1_2
      GNUTLS_TLS1_2,
#endif
      GNUTLS_TLS1_1, GNUTLS_TLS1, 0 };
    const int protocolPriority[] = { GNUTLS_TLS1, 0 };
    const int kxPriority[]       = { GNUTLS_KX_ANON_DH, 0 };
    const int cipherPriority[]   = { GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_AES_128_CBC,
                                     GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0 };
    const int compPriority[]     = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
    const int macPriority[]      = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
    gnutls_protocol_set_priority( *m_session, protocolPriority );
    gnutls_cipher_set_priority( *m_session, cipherPriority );
    gnutls_compression_set_priority( *m_session, compPriority );
    gnutls_kx_set_priority( *m_session, kxPriority );
    gnutls_mac_set_priority( *m_session, macPriority );
#endif

    gnutls_credentials_set( *m_session, GNUTLS_CRD_ANON, m_anoncred );

    gnutls_transport_set_ptr( *m_session, (gnutls_transport_ptr_t)this );
    gnutls_transport_set_push_function( *m_session, pushFunc );
    gnutls_transport_set_pull_function( *m_session, pullFunc );

    m_valid = true;
    return true;
  }
Exemple #14
0
  bool GnuTLSServerAnon::init( const std::string&,
                               const std::string&,
                               const StringList& )
  {
    const int protocolPriority[] = { GNUTLS_TLS1, 0 };
    const int kxPriority[]       = { GNUTLS_KX_ANON_DH, 0 };
    const int cipherPriority[]   = { GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_AES_128_CBC,
                                     GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0 };
    const int compPriority[]     = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
    const int macPriority[]      = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };

    if( m_initLib && gnutls_global_init() != 0 )
      return false;

    if( gnutls_anon_allocate_server_credentials( &m_anoncred ) < 0 )
      return false;

    generateDH();
    gnutls_anon_set_server_dh_params( m_anoncred, m_dhParams );

    if( gnutls_init( m_session, GNUTLS_SERVER ) != 0 )
      return false;

    gnutls_protocol_set_priority( *m_session, protocolPriority );
    gnutls_cipher_set_priority( *m_session, cipherPriority );
    gnutls_compression_set_priority( *m_session, compPriority );
    gnutls_kx_set_priority( *m_session, kxPriority );
    gnutls_mac_set_priority( *m_session, macPriority );
    gnutls_credentials_set( *m_session, GNUTLS_CRD_ANON, m_anoncred );

    gnutls_dh_set_prime_bits( *m_session, m_dhBits );

    gnutls_transport_set_ptr( *m_session, (gnutls_transport_ptr_t)this );
    gnutls_transport_set_push_function( *m_session, pushFunc );
    gnutls_transport_set_pull_function( *m_session, pullFunc );

    m_valid = true;
    return true;
  }
static int tls_gnutls_init_session(struct tls_global *global,
				   struct tls_connection *conn)
{
	const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
	const int protos[2] = { GNUTLS_TLS1, 0 };
	int ret;

	ret = gnutls_init(&conn->session,
			  global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
	if (ret < 0) {
		wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
			   "connection: %s", gnutls_strerror(ret));
		return -1;
	}

	ret = gnutls_set_default_priority(conn->session);
	if (ret < 0)
		goto fail;

	ret = gnutls_certificate_type_set_priority(conn->session, cert_types);
	if (ret < 0)
		goto fail;

	ret = gnutls_protocol_set_priority(conn->session, protos);
	if (ret < 0)
		goto fail;

	gnutls_transport_set_pull_function(conn->session, tls_pull_func);
	gnutls_transport_set_push_function(conn->session, tls_push_func);
	gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);

	return 0;

fail:
	wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
		   gnutls_strerror(ret));
	gnutls_deinit(conn->session);
	return -1;
}
Exemple #16
0
/**
 * tls_set_priority - Set the priority of various protocols
 * @param data TLS socket data
 * @retval  0 Success
 * @retval -1 Error
 */
static int tls_set_priority(struct TlsSockData *data)
{
  size_t nproto = 0; /* number of tls/ssl protocols */

  if (C_SslUseTlsv12)
    protocol_priority[nproto++] = GNUTLS_TLS1_2;
  if (C_SslUseTlsv11)
    protocol_priority[nproto++] = GNUTLS_TLS1_1;
  if (C_SslUseTlsv1)
    protocol_priority[nproto++] = GNUTLS_TLS1;
  if (C_SslUseSslv3)
    protocol_priority[nproto++] = GNUTLS_SSL3;
  protocol_priority[nproto] = 0;

  if (nproto == 0)
  {
    mutt_error(_("All available protocols for TLS/SSL connection disabled"));
    return -1;
  }

  if (C_SslCiphers)
  {
    mutt_error(
        _("Explicit ciphersuite selection via $ssl_ciphers not supported"));
  }
  if (certerr & CERTERR_INSECUREALG)
  {
    row++;
    strfcpy(menu->dialog[row], _("Warning: Server certificate was signed using an insecure algorithm"),
            dialog_row_len);
  }

  /* We use default priorities (see gnutls documentation),
   * except for protocol version */
  gnutls_set_default_priority(data->state);
  gnutls_protocol_set_priority(data->state, protocol_priority);
  return 0;
}
Exemple #17
0
static struct mailstream_ssl_data * ssl_data_new(int fd, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data)
{
  struct mailstream_ssl_data * ssl_data;
  gnutls_session session;
  struct mailstream_cancel * cancel;
  
  const int cipher_prio[] = { GNUTLS_CIPHER_AES_128_CBC,
		  		GNUTLS_CIPHER_3DES_CBC,
		  		GNUTLS_CIPHER_AES_256_CBC,
		  		GNUTLS_CIPHER_ARCFOUR_128, 0 };
  const int kx_prio[] = { GNUTLS_KX_DHE_RSA,
		  	   GNUTLS_KX_RSA, 
		  	   GNUTLS_KX_DHE_DSS, 0 };
  const int mac_prio[] = { GNUTLS_MAC_SHA1,
		  		GNUTLS_MAC_MD5, 0 };
  const int proto_prio[] = { GNUTLS_TLS1,
		  		  GNUTLS_SSL3, 0 };

  gnutls_certificate_credentials_t xcred;
  int r;
  struct mailstream_ssl_context * ssl_context = NULL;
  
  mailstream_ssl_init();
  
  if (gnutls_certificate_allocate_credentials (&xcred) != 0)
    return NULL;

  r = gnutls_init(&session, GNUTLS_CLIENT);
  if (session == NULL || r != 0)
    return NULL;
  
  if (callback != NULL) {
    ssl_context = mailstream_ssl_context_new(session, fd);
    callback(ssl_context, cb_data);
  }
  
  gnutls_session_set_ptr(session, ssl_context);
  gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
  gnutls_certificate_client_set_retrieve_function(xcred, mailstream_gnutls_client_cert_cb);

  gnutls_set_default_priority(session);
  gnutls_protocol_set_priority (session, proto_prio);
  gnutls_cipher_set_priority (session, cipher_prio);
  gnutls_kx_set_priority (session, kx_prio);
  gnutls_mac_set_priority (session, mac_prio);
  gnutls_record_disable_padding(session);
  gnutls_dh_set_prime_bits(session, 512);

  gnutls_transport_set_ptr(session, (gnutls_transport_ptr) fd);

  /* lower limits on server key length restriction */
  gnutls_dh_set_prime_bits(session, 512);
  
  do {
    r = gnutls_handshake(session);
  } while (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED);

  if (r < 0) {
    gnutls_perror(r);
    goto free_ssl_conn;
  }
  
  cancel = mailstream_cancel_new();
  if (cancel == NULL)
    goto free_ssl_conn;
  
  r = mailstream_prepare_fd(fd);
  if (r < 0)
    goto free_cancel;
  
  ssl_data = malloc(sizeof(* ssl_data));
  if (ssl_data == NULL)
    goto err;
  
  ssl_data->fd = fd;
  ssl_data->session = session;
  ssl_data->xcred = xcred;
  ssl_data->cancel = cancel;
  
  mailstream_ssl_context_free(ssl_context);

  return ssl_data;
  
 free_cancel:
  mailstream_cancel_free(cancel);
 free_ssl_conn:
  gnutls_certificate_free_credentials(xcred);
  mailstream_ssl_context_free(ssl_context);
  gnutls_deinit(session);
 err:
  return NULL;
}
Exemple #18
0
bool mrutils::TLSServer::use(mrutils::Socket* socket) {
    const char priorityEncryption[] = "NORMAL:+SRP";
    const int  priorityProtocols[]  = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };

    int ret; const char * err;

    //closeSession(); this->socket = socket;

    reader.use(*socket);

    mrutils::mutexAcquire(connectionMutex);

        std::cout << "gnutls_init" << std::endl;
        gnutls_init (&session, GNUTLS_SERVER);

        /* Encryption priorities */
        std::cout << "gnutls_priority_set_direct" << std::endl;
        ret = gnutls_priority_set_direct (session, priorityEncryption, &err);
        if (ret < 0) {
            if (ret == GNUTLS_E_INVALID_REQUEST) {
                fprintf (stderr, "Syntax error at: %s\n", err);
            }
            mrutils::mutexRelease(connectionMutex);
            return false;
        }

        /* Protocol priorities */ 
        std::cout << "gnutls_protocol_set_priority" << std::endl;
        ret = gnutls_protocol_set_priority(session, priorityProtocols);
        if (ret < 0) {
            printf("unable to set proto priority\n");
            mrutils::mutexRelease(connectionMutex);
            return false;
        }

        std::cout << "gnutls_credentials_set" << std::endl;
        gnutls_credentials_set (session, GNUTLS_CRD_SRP, srp_cred);
        std::cout << "gnutls_certificate_server_set_request" << std::endl;
        gnutls_certificate_server_set_request (session, GNUTLS_CERT_IGNORE);

        std::cout << "gnutls_transport_set_ptr " << socket->s_ << std::endl;
        gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) socket->s_);

        init_ = true;

        /* Perform the TLS handshake */
        std::cout << "gnutls_handshake" << std::endl;
        ret = gnutls_handshake (session);
        if (ret < 0) {
            fprintf (stderr, "*** Handshake failed\n");
            gnutls_perror (ret);
            mrutils::mutexRelease(connectionMutex);
            return false;
        }

        if (!reader.open( 
            fastdelegate::MakeDelegate(this
                ,&TLSServer::recv), (void*) session )) {
            printf("Unable to open mrutils::BufferedReader");
            mrutils::mutexRelease(connectionMutex);
            return false;
        }

    mrutils::mutexRelease(connectionMutex);

    return (connected_ = true);
}
Exemple #19
0
int vnc_tls_client_setup(struct VncState *vs,
                         int needX509Creds) {
    static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
    static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 };
    static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
    static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};

    VNC_DEBUG("Do TLS setup\n");
    if (vnc_tls_initialize() < 0) {
        VNC_DEBUG("Failed to init TLS\n");
        vnc_client_error(vs);
        return -1;
    }
    if (vs->tls.session == NULL) {
        if (gnutls_init(&vs->tls.session, GNUTLS_SERVER) < 0) {
            vnc_client_error(vs);
            return -1;
        }

        if (gnutls_set_default_priority(vs->tls.session) < 0) {
            gnutls_deinit(vs->tls.session);
            vs->tls.session = NULL;
            vnc_client_error(vs);
            return -1;
        }

        if (gnutls_kx_set_priority(vs->tls.session, needX509Creds ? kx_x509 : kx_anon) < 0) {
            gnutls_deinit(vs->tls.session);
            vs->tls.session = NULL;
            vnc_client_error(vs);
            return -1;
        }

        if (gnutls_certificate_type_set_priority(vs->tls.session, cert_type_priority) < 0) {
            gnutls_deinit(vs->tls.session);
            vs->tls.session = NULL;
            vnc_client_error(vs);
            return -1;
        }

        if (gnutls_protocol_set_priority(vs->tls.session, protocol_priority) < 0) {
            gnutls_deinit(vs->tls.session);
            vs->tls.session = NULL;
            vnc_client_error(vs);
            return -1;
        }

        if (needX509Creds) {
            gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(vs->vd);
            if (!x509_cred) {
                gnutls_deinit(vs->tls.session);
                vs->tls.session = NULL;
                vnc_client_error(vs);
                return -1;
            }
            if (gnutls_credentials_set(vs->tls.session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
                gnutls_deinit(vs->tls.session);
                vs->tls.session = NULL;
                gnutls_certificate_free_credentials(x509_cred);
                vnc_client_error(vs);
                return -1;
            }
            if (vs->vd->tls.x509verify) {
                VNC_DEBUG("Requesting a client certificate\n");
                gnutls_certificate_server_set_request (vs->tls.session, GNUTLS_CERT_REQUEST);
            }

        } else {
            gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred();
            if (!anon_cred) {
                gnutls_deinit(vs->tls.session);
                vs->tls.session = NULL;
                vnc_client_error(vs);
                return -1;
            }
            if (gnutls_credentials_set(vs->tls.session, GNUTLS_CRD_ANON, anon_cred) < 0) {
                gnutls_deinit(vs->tls.session);
                vs->tls.session = NULL;
                gnutls_anon_free_server_credentials(anon_cred);
                vnc_client_error(vs);
                return -1;
            }
        }

        gnutls_transport_set_ptr(vs->tls.session, (gnutls_transport_ptr_t)vs);
        gnutls_transport_set_push_function(vs->tls.session, vnc_tls_push);
        gnutls_transport_set_pull_function(vs->tls.session, vnc_tls_pull);
    }
    return 0;
}
Exemple #20
0
/* tls_negotiate: After TLS state has been initialised, attempt to negotiate
 *   TLS over the wire, including certificate checks. */
static int tls_negotiate (CONNECTION * conn)
{
  tlssockdata *data;
  int err;
  size_t nproto = 0; /* number of tls/ssl protocols */

  data = (tlssockdata *) safe_calloc (1, sizeof (tlssockdata));
  conn->sockdata = data;
  err = gnutls_certificate_allocate_credentials (&data->xcred);
  if (err < 0)
  {
    FREE(&conn->sockdata);
    mutt_error ("gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err));
    mutt_sleep (2);
    return -1;
  }

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

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

  if (SslClientCert)
  {
    dprint (2, (debugfile, "Using client certificate %s\n", SslClientCert));
    gnutls_certificate_set_x509_key_file (data->xcred, SslClientCert,
                                          SslClientCert, GNUTLS_X509_FMT_PEM);
  }

#if 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

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

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

  if (option(OPTTLSV1_2))
    protocol_priority[nproto++] = GNUTLS_TLS1_2;
  if (option(OPTTLSV1_1))
    protocol_priority[nproto++] = GNUTLS_TLS1_1;
  if (option(OPTTLSV1))
    protocol_priority[nproto++] = GNUTLS_TLS1;
  if (option(OPTSSLV3))
    protocol_priority[nproto++] = GNUTLS_SSL3;
  protocol_priority[nproto] = 0;

  /* disable TLS/SSL protocols as needed */
  if (nproto == 0)
  {
    mutt_error (_("All available protocols for TLS/SSL connection disabled"));
    goto fail;
  }
  /*
  else
    use the list set above
  */

  /* We use default priorities (see gnutls documentation),
     except for protocol version */
  gnutls_set_default_priority (data->state);
  gnutls_protocol_set_priority (data->state, protocol_priority);

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

/*
  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_E_INTERRUPTED)
  {
    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));
    }
    mutt_sleep (2);
    goto fail;
  }

  if (!tls_check_certificate(conn))
    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 (!option(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;
}
Exemple #21
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;
}
Exemple #22
0
static gnutls_session
tls_session_init(int side, uschar *expciphers, uschar *expmac, uschar *expkx,
  uschar *expproto)
{
gnutls_session session;

gnutls_init(&session, side);

/* Initialize the lists of permitted protocols, key-exchange methods, ciphers,
and MACs. */

memcpy(cipher_priority, default_cipher_priority, sizeof(cipher_priority));
memcpy(mac_priority, default_mac_priority, sizeof(mac_priority));
memcpy(kx_priority, default_kx_priority, sizeof(kx_priority));
memcpy(proto_priority, default_proto_priority, sizeof(proto_priority));

/* The names OpenSSL uses in tls_require_ciphers are of the form DES-CBC3-SHA,
using hyphen separators. GnuTLS uses underscore separators. So that I can use
either form for tls_require_ciphers in my tests, and also for general
convenience, we turn hyphens into underscores before scanning the list. */

if (expciphers != NULL)
  {
  uschar *s = expciphers;
  while (*s != 0) { if (*s == '-') *s = '_'; s++; }
  }

if ((expciphers != NULL &&
      !set_priority(cipher_priority, sizeof(cipher_priority)/sizeof(int),
        expciphers, cipher_index, sizeof(cipher_index)/sizeof(pri_item),
        US"cipher")) ||
    (expmac != NULL &&
      !set_priority(mac_priority, sizeof(mac_priority)/sizeof(int),
        expmac, mac_index, sizeof(mac_index)/sizeof(pri_item),
        US"MAC")) ||
    (expkx != NULL &&
      !set_priority(kx_priority, sizeof(kx_priority)/sizeof(int),
        expkx, kx_index, sizeof(kx_index)/sizeof(pri_item),
        US"key-exchange")) ||
    (expproto != NULL &&
      !set_priority(proto_priority, sizeof(proto_priority)/sizeof(int),
        expproto, proto_index, sizeof(proto_index)/sizeof(pri_item),
        US"protocol")))
  {
  gnutls_deinit(session);
  return NULL;
  }

/* Define the various priorities */

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, proto_priority);
gnutls_mac_set_priority(session, mac_priority);

gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);

gnutls_dh_set_prime_bits(session, DH_BITS);

/* Request or demand a certificate of the peer, as configured. This will
happen only in a server. */

if (verify_requirement != VERIFY_NONE)
  gnutls_certificate_server_set_request(session,
    (verify_requirement == VERIFY_OPTIONAL)?
      GNUTLS_CERT_REQUEST : GNUTLS_CERT_REQUIRE);

gnutls_db_set_cache_expiration(session, ssl_session_timeout);

/* Reduce security in favour of increased compatibility, if the admin
decides to make that trade-off. */
if (gnutls_compat_mode)
  {
#if LIBGNUTLS_VERSION_NUMBER >= 0x020104
  DEBUG(D_tls) debug_printf("lowering GnuTLS security, compatibility mode\n");
  gnutls_session_enable_compatibility_mode(session);
#else
  DEBUG(D_tls) debug_printf("Unable to set gnutls_compat_mode - GnuTLS version too old\n");
#endif
  }

DEBUG(D_tls) debug_printf("initialized GnuTLS session\n");
return session;
}
Exemple #23
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;
}
Exemple #24
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;
}
Exemple #25
0
TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr <security::cert::certificateVerifier> cv, shared_ptr <TLSProperties> props)
	: m_certVerifier(cv), m_props(props)
{
	int res;

	m_gnutlsSession = new gnutls_session;

	if (gnutls_init(m_gnutlsSession, GNUTLS_CLIENT) != 0)
		throw std::bad_alloc();

	// Sets some default priority on the ciphers, key exchange methods,
	// macs and compression methods.
#ifdef VMIME_HAVE_GNUTLS_PRIORITY_FUNCS
	gnutls_dh_set_prime_bits(*m_gnutlsSession, 128);

	if ((res = gnutls_priority_set_direct
		(*m_gnutlsSession, m_props->getCipherSuite().c_str(), NULL)) != 0)
	{
		throwTLSException("gnutls_priority_set_direct", res);
	}

#else  // !VMIME_HAVE_GNUTLS_PRIORITY_FUNCS

	gnutls_set_default_priority(*m_gnutlsSession);

	// 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.
	const int certTypePriority[] = { GNUTLS_CRT_X509, 0 };

	res = gnutls_certificate_type_set_priority
		(*m_gnutlsSession, certTypePriority);

	if (res < 0)
	{
		throwTLSException
			("gnutls_certificate_type_set_priority", res);
	}

	// Sets the priority on the protocol types
	const int protoPriority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };

	res = gnutls_protocol_set_priority(*m_gnutlsSession, protoPriority);

	if (res < 0)
	{
		throwTLSException
			("gnutls_certificate_type_set_priority", res);
	}

	// Priority on the ciphers
	const int cipherPriority[] =
	{
		GNUTLS_CIPHER_ARCFOUR_128,
		GNUTLS_CIPHER_3DES_CBC,
		GNUTLS_CIPHER_AES_128_CBC,
		GNUTLS_CIPHER_AES_256_CBC,
		GNUTLS_CIPHER_ARCFOUR_40,
		GNUTLS_CIPHER_RC2_40_CBC,
		GNUTLS_CIPHER_DES_CBC,
		0
	};

	gnutls_cipher_set_priority(*m_gnutlsSession, cipherPriority);

	// Priority on MACs
	const int macPriority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0};

	gnutls_mac_set_priority(*m_gnutlsSession, macPriority);

	// Priority on key exchange methods
	const int kxPriority[] =
	{
		GNUTLS_KX_RSA,
		GNUTLS_KX_DHE_DSS,
		GNUTLS_KX_DHE_RSA,
		GNUTLS_KX_ANON_DH,
		GNUTLS_KX_SRP,
		GNUTLS_KX_RSA_EXPORT,
		GNUTLS_KX_SRP_RSA,
		GNUTLS_KX_SRP_DSS,
		0
	};

	gnutls_kx_set_priority(*m_gnutlsSession, kxPriority);

	// Priority on compression methods
	const int compressionPriority[] =
	{
		GNUTLS_COMP_ZLIB,
		//GNUTLS_COMP_LZO,
		GNUTLS_COMP_NULL,
		0
	};

	gnutls_compression_set_priority(*m_gnutlsSession, compressionPriority);

#endif // !VMIME_HAVE_GNUTLS_PRIORITY_FUNCS

	// Initialize credentials
	gnutls_credentials_set(*m_gnutlsSession,
		GNUTLS_CRD_ANON, g_gnutlsGlobal.anonCred);

	gnutls_credentials_set(*m_gnutlsSession,
		GNUTLS_CRD_CERTIFICATE, g_gnutlsGlobal.certCred);
}