Exemple #1
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;
}
Exemple #2
0
Fichier : ssl.c Projet : 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;
}
Exemple #3
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 #4
0
struct connection_state *initialize_gnutls(intptr_t sd, char *name, Pop3 pc,
										   const char *remote_hostname)
{
	static int gnutls_initialized;
	int zok;
	struct connection_state *scs = malloc(sizeof(struct connection_state));
	memset(scs, 0, sizeof(struct connection_state));	/* clears the unprocessed buffer */

	scs->pc = pc;

	assert(sd >= 0);

	if (gnutls_initialized == 0) {
		assert(gnutls_global_init() == 0);
		gnutls_initialized = 1;
	}

	assert(gnutls_init(&scs->tls_state, GNUTLS_CLIENT) == 0);
	{
		const char *err_pos;
		if (GNUTLS_E_SUCCESS != gnutls_priority_set_direct(scs->tls_state, tls, &err_pos)) {
			DMA(DEBUG_ERROR,
				"Unable to set the priorities to use on the ciphers, "
				"key exchange methods, macs and/or compression methods.\n"
				"See 'tls' parameter in config file: '%s'.\n",
				err_pos);
			exit(1);
		}

		/* no client private key */
		if (gnutls_certificate_allocate_credentials(&scs->xcred) < 0) {
			DMA(DEBUG_ERROR, "gnutls memory error\n");
			exit(1);
		}

		/* certfile seems to work. */
		if (certificate_filename != NULL) {
			if (!exists(certificate_filename)) {
				DMA(DEBUG_ERROR,
					"Certificate file (certfile=) %s not found.\n",
					certificate_filename);
				exit(1);
			}
			zok = gnutls_certificate_set_x509_trust_file(scs->xcred,
					(char *)
					certificate_filename,
					GNUTLS_X509_FMT_PEM);
			if (zok < 0) {
				DMA(DEBUG_ERROR,
					"GNUTLS did not like your certificate file %s (%d).\n",
					certificate_filename, zok);
				gnutls_perror(zok);
				exit(1);
			}
		}

		gnutls_cred_set(scs->tls_state, GNUTLS_CRD_CERTIFICATE,
						scs->xcred);
		gnutls_transport_set_ptr(scs->tls_state,
								 (gnutls_transport_ptr_t) sd);
		do {
			zok = gnutls_handshake(scs->tls_state);
		}
		while (zok == GNUTLS_E_INTERRUPTED || zok == GNUTLS_E_AGAIN);

		tls_check_certificate(scs, remote_hostname);
	}

	if (zok < 0) {
		TDM(DEBUG_ERROR, "%s: Handshake failed\n", name);
		TDM(DEBUG_ERROR, "%s: This may be a problem in gnutls, "
			"which is under development\n", name);
		TDM(DEBUG_ERROR,
			"%s: This copy of wmbiff was compiled with \n"
			"  gnutls version %s.\n", name, LIBGNUTLS_VERSION);
		gnutls_perror(zok);
		if (scs->pc->u.pop_imap.serverPort != 143 /* starttls */ ) {
			TDM(DEBUG_ERROR,
				"%s: Please run 'gnutls-cli-debug -p %d %s' to test ssl directly.\n"
				"  That tool provides a lower-level test of gnutls with your server.\n",
				name, scs->pc->u.pop_imap.serverPort, remote_hostname);
		}
		gnutls_deinit(scs->tls_state);
		free(scs);
		return (NULL);
	} else {
		TDM(DEBUG_INFO, "%s: Handshake was completed\n", name);
		if (scs->pc->debug >= DEBUG_INFO)
			print_info(scs->tls_state, remote_hostname);
		scs->sd = sd;
		scs->name = name;
	}
	return (scs);
}