Пример #1
0
static void
ADD_MAC (gnutls_session session, int mac)
{
  static int _mac_priority[] = { 0, 0 };
  _mac_priority[0] = mac;

  gnutls_mac_set_priority (session, _mac_priority);
}
Пример #2
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;
}
Пример #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;
}
Пример #4
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
Пример #5
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;
}
Пример #6
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;
}
Пример #7
0
  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;
  }
Пример #8
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;
  }
Пример #9
0
static tls_session *
tlsg_session_new ( tls_ctx * ctx, int is_server )
{
	tlsg_ctx *c = (tlsg_ctx *)ctx;
	tlsg_session *session;

	session = ber_memcalloc ( 1, sizeof (*session) );
	if ( !session )
		return NULL;

	session->ctx = c;
	gnutls_init( &session->session, is_server ? GNUTLS_SERVER : GNUTLS_CLIENT );
#ifdef HAVE_CIPHERSUITES
	gnutls_priority_set( session->session, c->prios );
#else
	gnutls_set_default_priority( session->session );
	if ( c->kx_list ) {
		gnutls_kx_set_priority( session->session, c->kx_list );
		gnutls_cipher_set_priority( session->session, c->cipher_list );
		gnutls_mac_set_priority( session->session, c->mac_list );
	}
#endif
	if ( c->cred )
		gnutls_credentials_set( session->session, GNUTLS_CRD_CERTIFICATE, c->cred );
	
	if ( is_server ) {
		int flag = 0;
		if ( c->lo->ldo_tls_require_cert ) {
			flag = GNUTLS_CERT_REQUEST;
			if ( c->lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND ||
				c->lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD )
				flag = GNUTLS_CERT_REQUIRE;
			gnutls_certificate_server_set_request( session->session, flag );
		}
	}
	return (tls_session *)session;
} 
Пример #10
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;
}
Пример #11
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);
}
Пример #12
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;
}
Пример #13
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;
}