Esempio n. 1
0
static int
rb_epoll_sched_event_timerfd(struct ev_entry *event, int when)
{
	struct itimerspec ts;
	static char buf[FD_DESC_SZ + 8];
	int fd;
	rb_fde_t *F;

	if((fd = timerfd_create(CLOCK_REALTIME, 0)) < 0)
	{
		rb_lib_log("timerfd_create: %s\n", strerror(errno));
		return 0;
	}

	memset(&ts, 0, sizeof(ts));
	ts.it_value.tv_sec = when;
	ts.it_value.tv_nsec = 0;
	if(event->frequency != 0)
		ts.it_interval = ts.it_value;

	if(timerfd_settime(fd, 0, &ts, NULL) < 0)
	{
		rb_lib_log("timerfd_settime: %s\n", strerror(errno));
		close(fd);
		return 0;
	}
	rb_snprintf(buf, sizeof(buf), "timerfd: %s", event->name);
	F = rb_open(fd, RB_FD_UNKNOWN, buf);
	rb_set_nb(F);
	event->comm_ptr = F;
	rb_setselect(F, RB_SELECT_READ, rb_read_timerfd, event);
	return 1;
}
Esempio n. 2
0
static int
rb_epoll_sched_event_signalfd(struct ev_entry *event, int when)
{
	timer_t *id;
	struct sigevent ev;
	struct itimerspec ts;

	memset(&ev, 0, sizeof(ev));
	event->comm_ptr = rb_malloc(sizeof(timer_t));
	id = event->comm_ptr;
	ev.sigev_notify = SIGEV_SIGNAL;
	ev.sigev_signo = RTSIGNAL;
	ev.sigev_value.sival_ptr = event;

	if(timer_create(CLOCK_REALTIME, &ev, id) < 0)
	{
		rb_lib_log("timer_create: %s\n", strerror(errno));
		return 0;
	}
	memset(&ts, 0, sizeof(ts));
	ts.it_value.tv_sec = when;
	ts.it_value.tv_nsec = 0;
	if(event->frequency != 0)
		ts.it_interval = ts.it_value;

	if(timer_settime(*id, 0, &ts, NULL) < 0)
	{
		rb_lib_log("timer_settime: %s\n", strerror(errno));
		return 0;
	}
	return 1;
}
Esempio n. 3
0
int
rb_init_ssl(void)
{
	int ret = 1;
	char libratbox_data[] = "libratbox data";
	SSL_load_error_strings();
	SSL_library_init();
	libratbox_index = SSL_get_ex_new_index(0, libratbox_data, NULL, NULL, NULL);
	ssl_server_ctx = SSL_CTX_new(SSLv23_server_method());
	if(ssl_server_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s",
			   get_ssl_error(ERR_get_error()));
		ret = 0;
	}
	/* Disable SSLv2, make the client use our settings */
	SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_SSLv2 | SSL_OP_CIPHER_SERVER_PREFERENCE);
	SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);

	ssl_client_ctx = SSL_CTX_new(TLSv1_client_method());

	if(ssl_client_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s",
			   get_ssl_error(ERR_get_error()));
		ret = 0;
	}
	return ret;
}
Esempio n. 4
0
rb_ssl_ctx *
rb_setup_ssl_client(const char *ssl_cipher_list, const char *cert, const char *keyfile)
{	
	int ret;
	rb_ssl_ctx *sctx;
	
	sctx = rb_malloc(sizeof(rb_ssl_ctx));

	mbedtls_ssl_config_init(&sctx->config);

	if ((ret = mbedtls_ssl_config_defaults(&sctx->config,
		MBEDTLS_SSL_IS_CLIENT,
		MBEDTLS_SSL_TRANSPORT_STREAM,
		MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
	{
		rb_lib_log("rb_init_ssl: unable to initialize default SSL parameters for client context: -0x%x", -ret);
		return 0;
	}
	
	mbedtls_ssl_conf_rng(&sctx->config, mbedtls_ctr_drbg_random, &ctr_drbg);

	mbedtls_ssl_conf_authmode(&sctx->config, MBEDTLS_SSL_VERIFY_NONE);

	if(cert != NULL && keyfile != NULL)
	{
		mbedtls_x509_crt_init(&sctx->x509);
		ret = mbedtls_x509_crt_parse_file(&sctx->x509, cert);
		if (ret != 0)
		{
			rb_lib_log("rb_setup_ssl_client: failed to parse certificate '%s': -0x%x", cert, -ret);
			return 0;
		}

		mbedtls_pk_init(&sctx->serv_pk);
		ret = mbedtls_pk_parse_keyfile(&sctx->serv_pk, keyfile, NULL);
		if (ret != 0)
		{
			rb_lib_log("rb_setup_ssl_client: failed to parse private key '%s': -0x%x", keyfile, -ret);
			return 0;
		}

		if (&sctx->x509.next)
			mbedtls_ssl_conf_ca_chain(&sctx->config, sctx->x509.next, NULL);

		if ((ret = mbedtls_ssl_conf_own_cert(&sctx->config, &sctx->x509, &sctx->serv_pk)) != 0)
		{
			rb_lib_log("rb_setup_ssl_client: failed to set up own certificate: -0x%x", -ret);
			return 0;
		}
	}
	return sctx;



}
Esempio n. 5
0
rb_ssl_ctx *
rb_setup_ssl_client(const char *ssl_cipher_list, const char *cert, const char *keyfile)
{
	/* this needs to have more customizations etc...client certificates perhaps as well */
	rb_ssl_ctx *sctx;
	
	sctx = rb_malloc(sizeof(rb_ssl_ctx));	
	sctx->refcount = 1;
        sctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
        
        SSL_CTX_set_options(sctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION);
        if(sctx->ssl_ctx == NULL)
        {
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s",
			    ERR_error_string(ERR_get_error(), NULL));
		rb_free(sctx);
		return NULL;
	}
	
	if(ssl_cipher_list != NULL)
	{
		if(!SSL_CTX_set_cipher_list(sctx->ssl_ctx, ssl_cipher_list))
		{
			rb_lib_log("rb_setup_ssl_client: Error setting ssl_cipher_list=\"%s\": %s",
				   ssl_cipher_list, ERR_error_string(ERR_get_error(), NULL));
                        goto cleanup;
		}
	}
	
	if(cert != NULL && keyfile != NULL)
	{
	        if(!SSL_CTX_use_PrivateKey_file(sctx->ssl_ctx, keyfile, SSL_FILETYPE_PEM))
	        {
	                rb_lib_log("rb_setup_ssl_client: Error loading keyfile :%s", ERR_error_string(ERR_get_error(), NULL));
	                goto cleanup;
	        }
	        if(!SSL_CTX_use_certificate_chain_file(sctx->ssl_ctx, cert))
	        {
	                rb_lib_log("rb_setup_ssl_client: Error loading certificate :%s", ERR_error_string(ERR_get_error(), NULL));
	                goto cleanup;
	        }
	}
	return sctx;

cleanup:
        SSL_CTX_free(sctx->ssl_ctx);
        rb_free(sctx);
        return NULL;        
}
Esempio n. 6
0
int
rb_init_ssl(void)
{
	int ret = 1;
	char libratbox_data[] = "libratbox data";
	SSL_load_error_strings();
	SSL_library_init();
	libratbox_index = SSL_get_ex_new_index(0, libratbox_data, NULL, NULL, NULL);
	ssl_server_ctx = SSL_CTX_new(SSLv23_server_method());
	if(ssl_server_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s",
			   get_ssl_error(ERR_get_error()));
		ret = 0;
	}
	/* Disable SSLv2, make the client use our settings */
	SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_SSLv2 | SSL_OP_CIPHER_SERVER_PREFERENCE
#ifdef SSL_OP_SINGLE_DH_USE
			| SSL_OP_SINGLE_DH_USE
#endif
			);
	SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
	SSL_CTX_set_session_id_context(ssl_server_ctx,
			(const unsigned char *)"libratbox", 9);
	SSL_CTX_set_cipher_list(ssl_server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL");

	/* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available because redhat are dicks
	   and bastardise their OpenSSL for stupid reasons... */
	#if (OPENSSL_VERSION_NUMBER >= 0x10000000) && defined(NID_secp384r1)
		EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1);
		if (key) {
			SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key);
			EC_KEY_free(key);
		}
#ifdef SSL_OP_SINGLE_ECDH_USE
		SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_ECDH_USE);
#endif
	#endif

	ssl_client_ctx = SSL_CTX_new(TLSv1_client_method());

	if(ssl_client_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s",
			   get_ssl_error(ERR_get_error()));
		ret = 0;
	}
	return ret;
}
Esempio n. 7
0
void
rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, rb_socklen_t addrlen)
{
	if(new_F->sctx == NULL)
		return;

	new_F->type |= RB_FD_SSL;
	new_F->ssl = SSL_new(new_F->sctx->ssl_ctx);

	if(new_F->ssl == NULL)
	{
		new_F->sslerr.ssl_errno = get_last_err();
		rb_lib_log("rb_ssl_accept_setup: SSL_new() fails: %s", ERR_error_string(new_F->sslerr.ssl_errno, NULL));
		new_F->accept->callback(new_F, RB_ERROR_SSL, NULL, 0, new_F->accept->data);
		return;
	}
	
	new_F->accept = rb_malloc(sizeof(struct acceptdata));

	new_F->accept->callback = F->accept->callback;
	new_F->accept->data = F->accept->data;
	rb_settimeout(new_F, 10, rb_ssl_timeout, NULL);
	memcpy(&new_F->accept->S, st, addrlen);
	new_F->accept->addrlen = addrlen;

	SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F));
	rb_setup_ssl_cb(new_F);
	rb_ssl_accept_common(new_F);
}
Esempio n. 8
0
void
rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout)
{
	if(new_F->sctx == NULL)
		return;

	new_F->type |= RB_FD_SSL;
	new_F->ssl = SSL_new(new_F->sctx->ssl_ctx);
	if(new_F->ssl == NULL)
	{
		new_F->sslerr.ssl_errno = get_last_err();
		rb_lib_log("rb_ssl_start_accepted: SSL_new() fails: %s", ERR_error_string(new_F->sslerr.ssl_errno, NULL));
		cb(new_F, RB_ERROR_SSL, NULL, 0, data); 
		return;
	}

	new_F->accept = rb_malloc(sizeof(struct acceptdata));

	new_F->accept->callback = cb;
	new_F->accept->data = data;
	rb_settimeout(new_F, timeout, rb_ssl_timeout, NULL);

	new_F->accept->addrlen = 0;
	SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F));
	rb_setup_ssl_cb(new_F);
	rb_ssl_accept_common(new_F);
}
Esempio n. 9
0
int
rb_ssl_get_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN])
{
	const mbedtls_x509_crt *peer_cert;
	uint8_t hash[RB_SSL_CERTFP_LEN];
	const mbedtls_md_info_t *md_info;
	int ret;

	peer_cert = mbedtls_ssl_get_peer_cert(SSL_P(F));
	if (peer_cert == NULL)
		return 0;

	md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
	if (md_info == NULL)
		return 0;

	if ((ret = mbedtls_md(md_info, peer_cert->raw.p, peer_cert->raw.len, hash)) != 0)
	{
		rb_lib_log("rb_get_ssl_certfp: unable to get certfp for F: %p, %d", F, ret);
		return 0;
	}

	memcpy(certfp, hash, RB_SSL_CERTFP_LEN);

	return 1;
}
Esempio n. 10
0
static void
rb_read_timerfd(rb_fde_t *F, void *data)
{
	struct ev_entry *event = (struct ev_entry *)data;
	int retlen;
	uint64_t count;

	if(event == NULL)
	{
		rb_close(F);
		return;
	}

	retlen = rb_read(F, &count, sizeof(count));

	if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
	{
		rb_close(F);
		rb_lib_log("rb_read_timerfd: timerfd[%s] closed on error: %s", event->name,
			   strerror(errno));
		return;
	}
	rb_setselect(F, RB_SELECT_READ, rb_read_timerfd, event);
	rb_run_event(event);
}
Esempio n. 11
0
int
rb_init_ssl(void)
{
	int ret;
	mbedtls_entropy_init(&entropy);
	mbedtls_ctr_drbg_init(&ctr_drbg);


	if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0)) != 0)
	{
		rb_lib_log("rb_init_prng: unable to initialize PRNG, mbedtls_ctr_drbg_seed() returned -0x%x", -ret);
		return 0;
	}
#if 0
	mbedtls_ssl_config_init(&serv_config);

	if ((ret = mbedtls_ssl_config_defaults(&serv_config,
		MBEDTLS_SSL_IS_SERVER,
		MBEDTLS_SSL_TRANSPORT_STREAM,
		MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
	{
		rb_lib_log("rb_init_ssl: unable to initialize default SSL parameters for server context: -0x%x", -ret);
		return 0;
	}
#endif
//	mbedtls_ssl_conf_rng(&serv_config, mbedtls_ctr_drbg_random, &ctr_drbg);

	/***************************************************************************************************************/
#if 0
	mbedtls_ssl_config_init(&client_config);

	if ((ret = mbedtls_ssl_config_defaults(&client_config,
		MBEDTLS_SSL_IS_CLIENT,
		MBEDTLS_SSL_TRANSPORT_STREAM,
		MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
	{
		rb_lib_log("rb_init_ssl: unable to initialize default SSL parameters for client context: -0x%x", -ret);
		return 0;
	}

	mbedtls_ssl_conf_rng(&client_config, mbedtls_ctr_drbg_random, &ctr_drbg);
#endif
	return 1;
}
Esempio n. 12
0
/*
 * rb_setselect
 *
 * This is a needed exported function which will be called to register
 * and deregister interest in a pending IO state for a given FD.
 */
void
rb_setselect_epoll(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
{
	struct epoll_event ep_event;
	int old_flags = F->pflags;
	int op = -1;

	lrb_assert(IsFDOpen(F));

	/* Update the list, even though we're not using it .. */
	if(type & RB_SELECT_READ)
	{
		if(handler != NULL)
			F->pflags |= EPOLLIN;
		else
			F->pflags &= ~EPOLLIN;
		F->read_handler = handler;
		F->read_data = client_data;
	}

	if(type & RB_SELECT_WRITE)
	{
		if(handler != NULL)
			F->pflags |= EPOLLOUT;
		else
			F->pflags &= ~EPOLLOUT;
		F->write_handler = handler;
		F->write_data = client_data;
	}

	if(old_flags == 0 && F->pflags == 0)
		return;
	else if(F->pflags <= 0)
		op = EPOLL_CTL_DEL;
	else if(old_flags == 0 && F->pflags > 0)
		op = EPOLL_CTL_ADD;
	else if(F->pflags != old_flags)
		op = EPOLL_CTL_MOD;

	if(op == -1)
		return;

	ep_event.events = F->pflags;
	ep_event.data.ptr = F;

	if(op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD)
		ep_event.events |= EPOLLET;

	if(epoll_ctl(ep_info->ep, op, F->fd, &ep_event) != 0)
	{
		rb_lib_log("rb_setselect_epoll(): epoll_ctl failed: %s", strerror(errno));
		abort();
	}


}
Esempio n. 13
0
void
rb_outofmemory(void)
{
	static int was_here = 0;
	if (was_here)
		abort();
	was_here = 1;
	rb_lib_log("Out of memory: restarting server...");
	rb_lib_restart("Out of Memory");
}
Esempio n. 14
0
void
rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout)
{
	ssl_connect_t *sconn;
	int ssl_err;
	if(F == NULL)
		return;

	sconn = rb_malloc(sizeof(ssl_connect_t));
	sconn->data = data;
	sconn->callback = callback;
	sconn->timeout = timeout;
	F->connect = rb_malloc(sizeof(struct conndata));
	F->connect->callback = callback;
	F->connect->data = data;
	F->type |= RB_FD_SSL;
	F->ssl = SSL_new(F->sctx->ssl_ctx);

        if(F->ssl == NULL)
        {
                F->sslerr.ssl_errno = get_last_err();
                rb_lib_log("rb_ssl_start_Connected: SSL_new() fails: %s", ERR_error_string(F->sslerr.ssl_errno, NULL));
                
                rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
                return;
        }

	SSL_set_fd((SSL *) F->ssl, F->fd);
	rb_setup_ssl_cb(F);
	rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
	if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
	{
		switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
		{
		case SSL_ERROR_SYSCALL:
			if(rb_ignore_errno(errno))
		case SSL_ERROR_WANT_READ:
		case SSL_ERROR_WANT_WRITE:
				{
					F->sslerr.ssl_errno = get_last_err();
					rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE,
						     rb_ssl_tryconn_cb, sconn);
					return;
				}
		default:
			F->sslerr.ssl_errno = get_last_err();
			rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
			return;
		}
	}
	else
	{
		rb_ssl_connect_realcb(F, RB_OK, sconn);
	}
}
Esempio n. 15
0
int
rb_init_ssl(void)
{
    gnutls_global_init();

    if (gnutls_certificate_allocate_credentials(&x509) != GNUTLS_E_SUCCESS)
    {
        rb_lib_log("rb_init_ssl: Unable to allocate SSL/TLS certificate credentials");
        return 0;
    }
    rb_event_addish("rb_gcry_random_seed", rb_gcry_random_seed, NULL, 300);
    return 1;
}
Esempio n. 16
0
int
rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile)
{
	int ret;
	gnutls_datum_t *d_cert, *d_key;
	if(cert == NULL)
	{
		rb_lib_log("rb_setup_ssl_server: No certificate file");
		return 0;
	}

	if((d_cert = rb_load_file_into_datum_t(cert)) == NULL)
	{
		rb_lib_log("rb_setup_ssl_server: Error loading certificate: %s", strerror(errno));
		return 0;
	}

	if((d_key = rb_load_file_into_datum_t(keyfile)) == NULL)
	{
		rb_lib_log("rb_setup_ssl_server: Error loading key: %s", strerror(errno));
		return 0;
	}


	if((ret =
	    gnutls_certificate_set_x509_key_mem(x509, d_cert, d_key,
						GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS)
	{
		rb_lib_log("rb_setup_ssl_server: Error loading certificate or key file: %s",
			   gnutls_strerror(ret));
		return 0;
	}
	rb_free_datum_t(d_cert);
	rb_free_datum_t(d_key);

	if(dhfile != NULL)
	{
		if(gnutls_dh_params_init(&dh_params) == GNUTLS_E_SUCCESS)
		{
			gnutls_datum_t *data;
			int xret;
			data = rb_load_file_into_datum_t(dhfile);
			if(data != NULL)
			{
				xret = gnutls_dh_params_import_pkcs3(dh_params, data,
								     GNUTLS_X509_FMT_PEM);
				if(xret < 0)
					rb_lib_log
						("rb_setup_ssl_server: Error parsing DH file: %s\n",
						 gnutls_strerror(xret));
				rb_free_datum_t(data);
			}
			gnutls_certificate_set_dh_params(x509, dh_params);
		}
		else
			rb_lib_log("rb_setup_ssl_server: Unable to setup DH parameters");
	}
	return 1;
}
Esempio n. 17
0
int
rb_ports_sched_event(struct ev_entry *event, int when)
{
	timer_t *id;
	struct sigevent ev;
	port_notify_t not;
	struct itimerspec ts;

	event->comm_ptr = rb_malloc(sizeof(timer_t));
	id = event->comm_ptr;

	memset(&ev, 0, sizeof(ev));
	ev.sigev_notify = SIGEV_PORT;
	ev.sigev_value.sival_ptr = &not;

	memset(&not, 0, sizeof(not));
	not.portnfy_port = pe;
	not.portnfy_user = event;

	if(timer_create(CLOCK_REALTIME, &ev, id) < 0)
	{
		rb_lib_log("timer_create: %s\n", strerror(errno));
		return 0;
	}

	memset(&ts, 0, sizeof(ts));
	ts.it_value.tv_sec = when;
	ts.it_value.tv_nsec = 0;
	if(event->frequency != 0)
		ts.it_interval = ts.it_value;

	if(timer_settime(*id, 0, &ts, NULL) < 0)
	{
		rb_lib_log("timer_settime: %s\n", strerror(errno));
		return 0;
	}
	return 1;
}
Esempio n. 18
0
static void
rb_ssl_tryconn(rb_fde_t *F, int status, void *data)
{
	ssl_connect_t *sconn = data;
	int ssl_err;
	if(status != RB_OK)
	{
		rb_ssl_connect_realcb(F, status, sconn);
		return;
	}

	F->type |= RB_FD_SSL;
	F->ssl = SSL_new(F->sctx->ssl_ctx);

	if(F->ssl == NULL)
	{
		F->sslerr.ssl_errno = get_last_err();
		rb_lib_log("rb_ssl_tryconn: SSL_new() fails: %s", ERR_error_string(F->sslerr.ssl_errno, NULL));
		rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
		return;
	}
	
	SSL_set_fd((SSL *) F->ssl, F->fd);
	rb_setup_ssl_cb(F);
	rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
	if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
	{
		switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err))
		{
		case SSL_ERROR_SYSCALL:
			if(rb_ignore_errno(errno))
		case SSL_ERROR_WANT_READ:
		case SSL_ERROR_WANT_WRITE:
				{
					F->sslerr.ssl_errno = get_last_err();
					rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE,
						     rb_ssl_tryconn_cb, sconn);
					return;
				}
		default:
			F->sslerr.ssl_errno = get_last_err();
			rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
			return;
		}
	}
	else
	{
		rb_ssl_connect_realcb(F, RB_OK, sconn);
	}
}
Esempio n. 19
0
static void
rb_ssl_setup_client_context(rb_fde_t *F)
{
	int ret;

	mbedtls_ssl_init(SSL_P(ssl));
	if ((ret = mbedtls_ssl_setup(SSL_P(F), &F->sctx->config)) != 0)
	{
		rb_lib_log("rb_ssl_setup_client_context: failed to set up ssl context: -0x%x", -ret);
		rb_close(F);
		return;
	}

	mbedtls_ssl_set_bio(SSL_P(ssl), F, rb_ssl_write_cb, rb_ssl_read_cb, NULL);
}
Esempio n. 20
0
/*
 * rb_init_netio
 *
 * This is a needed exported function which will be called to initialise
 * the network loop code.
 */
int
rb_init_netio_devpoll(void)
{
	dpfd = open("/dev/poll", O_RDWR);
	if(dpfd < 0)
	{
		return errno;
	}
	maxfd = getdtablesize() - 2;	/* This makes more sense than HARD_FDLIMIT */
	fdmask = rb_malloc(sizeof(fdmask) * maxfd + 1);
	if(rb_open(dpfd, RB_FD_UNKNOWN, "/dev/poll file descriptor") == NULL)
	{
		rb_lib_log("rb_init_netio_devpoll: Unable to rb_open /dev/poll fd");
		return -1;
	}
	return 0;
}
Esempio n. 21
0
/*
 * Write an update to the devpoll filter.
 * See, we end up having to do a seperate (?) remove before we do an
 * add of a new polltype, so we have to have this function seperate from
 * the others.
 */
static void
devpoll_write_update(int fd, int events)
{
	struct pollfd pollfds[1];	/* Just to be careful */
	int retval;

	/* Build the pollfd entry */
	pollfds[0].revents = 0;
	pollfds[0].fd = fd;
	pollfds[0].events = events;

	/* Write the thing to our poll fd */
	retval = write(dpfd, &pollfds[0], sizeof(struct pollfd));
	if(retval != sizeof(struct pollfd))
		rb_lib_log("devpoll_write_update: dpfd write failed %d: %s", errno,
			   strerror(errno));
	/* Done! */
}
Esempio n. 22
0
int
rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile)
{
    DH *dh;
    unsigned long err;
    if(cert == NULL) {
        rb_lib_log("rb_setup_ssl_server: No certificate file");
        return 0;
    }
    if(!SSL_CTX_use_certificate_chain_file(ssl_server_ctx, cert) || !SSL_CTX_use_certificate_chain_file(ssl_client_ctx, cert)) {
        err = ERR_get_error();
        rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", cert,
                   get_ssl_error(err));
        return 0;
    }

    if(keyfile == NULL) {
        rb_lib_log("rb_setup_ssl_server: No key file");
        return 0;
    }


    if(!SSL_CTX_use_PrivateKey_file(ssl_server_ctx, keyfile, SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(ssl_client_ctx, keyfile, SSL_FILETYPE_PEM)) {
        err = ERR_get_error();
        rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile,
                   get_ssl_error(err));
        return 0;
    }

    if(dhfile != NULL) {
        /* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */
        BIO *bio = BIO_new_file(dhfile, "r");
        if(bio != NULL) {
            dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
            if(dh == NULL) {
                err = ERR_get_error();
                rb_lib_log
                ("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
                 dhfile, get_ssl_error(err));
                BIO_free(bio);
                return 0;
            }
            BIO_free(bio);
            SSL_CTX_set_tmp_dh(ssl_server_ctx, dh);
        } else {
            err = ERR_get_error();
            rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
                       dhfile, get_ssl_error(err));
        }
    }
    return 1;
}
Esempio n. 23
0
/*
 * rb_init_netio
 *
 * This is a needed exported function which will be called to initialise
 * the network loop code.
 */
int
rb_init_netio_epoll(void)
{
	can_do_event = 0;	/* shut up gcc */
	can_do_timerfd = 0;
	ep_info = rb_malloc(sizeof(struct epoll_info));
	ep_info->pfd_size = getdtablesize();
	ep_info->ep = epoll_create(ep_info->pfd_size);
	if(ep_info->ep < 0)
	{
		return -1;
	}

	if(rb_open(ep_info->ep, RB_FD_UNKNOWN, "epoll file descriptor") == NULL)
	{
		rb_lib_log("Unable to rb_open epoll fd");
		return -1;
	}
	ep_info->pfd = rb_malloc(sizeof(struct epoll_event) * ep_info->pfd_size);

	return 0;
}
Esempio n. 24
0
/*
 * rb_init_netio
 *
 * This is a needed exported function which will be called to initialise
 * the network loop code.
 */
int
rb_init_netio_kqueue(void)
{
	kq = kqueue();
	if(kq < 0)
	{
		return errno;
	}
	kqmax = getdtablesize();
	kqlst = rb_malloc(sizeof(struct kevent) * kqmax);
	kqout = rb_malloc(sizeof(struct kevent) * kqmax);
	if(rb_open(kq, RB_FD_UNKNOWN, "kqueue fd") == NULL)
	{
		rb_lib_log("rb_init_netio_kqueue: unable to rb_open kqueue fd");
		return -1;
	}
	
	zero_timespec.tv_sec = 0;
	zero_timespec.tv_nsec = 0;

	return 0;
}
Esempio n. 25
0
int
rb_init_ssl(void)
{
	gnutls_global_init();

	if(gnutls_certificate_allocate_credentials(&x509) != GNUTLS_E_SUCCESS)
	{
		rb_lib_log("rb_init_ssl: Unable to allocate SSL/TLS certificate credentials");
		return 0;
	}

#if GNUTLS_VERSION_MAJOR < 3
	gnutls_certificate_client_set_retrieve_function(x509, cert_callback);
#else
	gnutls_certificate_set_retrieve_function(x509, cert_callback);
#endif

#if (GNUTLS_VERSION_MAJOR < 3)
	rb_event_addish("rb_gcry_random_seed", rb_gcry_random_seed, NULL, 300);
#endif

	return 1;
}
Esempio n. 26
0
static void
kq_update_events(rb_fde_t *F, short filter, PF * handler)
{
	PF *cur_handler;
	int kep_flags;

	switch (filter)
	{
	case EVFILT_READ:
		cur_handler = F->read_handler;
		break;
	case EVFILT_WRITE:
		cur_handler = F->write_handler;
		break;
	default:
		/* XXX bad! -- adrian */
		return;
		break;
	}

	if((cur_handler == NULL && handler != NULL) || (cur_handler != NULL && handler == NULL))
	{
		struct kevent *kep;

		kep = kqlst + kqoff;

		if(handler != NULL)
		{
			kep_flags = EV_ADD | EV_ONESHOT;
		}
		else
		{
			kep_flags = EV_DELETE;
		}

		EV_SET(kep, (uintptr_t)F->fd, filter, kep_flags, 0, 0, (void *)F);

		if(++kqoff == kqmax)
		{
			int ret, i;

			/* Add them one at a time, because there may be
			 * already closed fds in it. The kernel will try
			 * to report invalid fds in the output; if there
			 * is no space, it silently stops processing the
			 * array at that point. We cannot give output space
			 * because that would also return events we cannot
			 * process at this point.
			 */
			for(i = 0; i < kqoff; i++)
			{
				ret = kevent(kq, kqlst + i, 1, NULL, 0, &zero_timespec);
				/* jdc -- someone needs to do error checking... */
				/* EBADF is normal here -- jilles */
				if(ret == -1 && errno != EBADF)
					rb_lib_log("kq_update_events(): kevent(): %s",
						   strerror(errno));
			}
			kqoff = 0;
		}
	}
}
Esempio n. 27
0
int
rb_init_ssl(void)
{
	int ret = 1;
	char libratbox_data[] = "libratbox data";
	const char libratbox_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL";
	SSL_load_error_strings();
	SSL_library_init();
	libratbox_index = SSL_get_ex_new_index(0, libratbox_data, NULL, NULL, NULL);

#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L)
	ssl_server_ctx = SSL_CTX_new(SSLv23_server_method());
#else
	ssl_server_ctx = SSL_CTX_new(TLS_server_method());
#endif

	if(ssl_server_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s",
			   get_ssl_error(ERR_get_error()));
		ret = 0;
	}

	long server_options = SSL_CTX_get_options(ssl_server_ctx);

#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L)
	server_options |= SSL_OP_NO_SSLv2;
	server_options |= SSL_OP_NO_SSLv3;
#endif

#ifdef SSL_OP_SINGLE_DH_USE
	server_options |= SSL_OP_SINGLE_DH_USE;
#endif

#ifdef SSL_OP_SINGLE_ECDH_USE
	server_options |= SSL_OP_SINGLE_ECDH_USE;
#endif

#ifdef SSL_OP_NO_TICKET
	server_options |= SSL_OP_NO_TICKET;
#endif

	server_options |= SSL_OP_CIPHER_SERVER_PREFERENCE;

	SSL_CTX_set_options(ssl_server_ctx, server_options);
	SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
	SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF);
	SSL_CTX_set_cipher_list(ssl_server_ctx, libratbox_ciphers);

	/* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available because redhat are dicks
	   and bastardise their OpenSSL for stupid reasons... */
	#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && defined(NID_secp384r1)
		EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1);
		if (key) {
			SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key);
			EC_KEY_free(key);
		}
	#endif

#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L)
	ssl_client_ctx = SSL_CTX_new(TLSv1_client_method());
#else
	ssl_client_ctx = SSL_CTX_new(TLS_client_method());
#endif

	if(ssl_client_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s",
			   get_ssl_error(ERR_get_error()));
		ret = 0;
	}

#ifdef SSL_OP_NO_TICKET
	SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET);
#endif

	SSL_CTX_set_cipher_list(ssl_client_ctx, libratbox_ciphers);

	return ret;
}
Esempio n. 28
0
rb_ssl_ctx *
rb_setup_ssl_server(const char *cacert, const char *cert, const char *keyfile, const char *dhfile, const char *ssl_cipher_list, const char *named_curve, rb_tls_ver_t tls_min_ver)
{
	int ret;
	rb_ssl_ctx *sctx;
	
	sctx = rb_malloc(sizeof(rb_ssl_ctx));

	mbedtls_ssl_config_init(&sctx->config);
//	mbedtls_entropy_init(&sctx->entropy);
//	mbedtls_ctr_drbg_init(&sctx->ctr_drbg);
	mbedtls_ssl_conf_rng(&sctx->config, mbedtls_ctr_drbg_random, &ctr_drbg);


	if ((ret = mbedtls_ssl_config_defaults(&sctx->config,
		MBEDTLS_SSL_IS_SERVER,
		MBEDTLS_SSL_TRANSPORT_STREAM,
		MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
	{
		rb_lib_log("rb_init_ssl: unable to initialize default SSL parameters for server context: -0x%x", -ret);
		return 0;
	}

	mbedtls_ssl_conf_rng(&sctx->config, mbedtls_ctr_drbg_random, &ctr_drbg);


	if(cacert != NULL)
	{
        	mbedtls_x509_crt_init(&sctx->cacert);
        	ret = mbedtls_x509_crt_parse_file(&sctx->cacert, cacert);
        	if(ret != 0)
        	{
        		rb_lib_log("rb_setup_ssl_server: failed to parse CA certificate '%s': -0x%x", cert, -ret);
        		return 0;
        	}
	}
	
	mbedtls_x509_crt_init(&sctx->x509);
	ret = mbedtls_x509_crt_parse_file(&sctx->x509, cert);
	if (ret != 0)
	{
		rb_lib_log("rb_setup_ssl_server: failed to parse certificate '%s': -0x%x", cert, -ret);
		return 0;
	}

	mbedtls_pk_init(&sctx->serv_pk);
	ret = mbedtls_pk_parse_keyfile(&sctx->serv_pk, keyfile, NULL);
	if (ret != 0)
	{
		rb_lib_log("rb_setup_ssl_server: failed to parse private key '%s': -0x%x", keyfile, -ret);
		return 0;
	}

	mbedtls_dhm_init(&sctx->dh_params);
	ret = mbedtls_dhm_parse_dhmfile(&sctx->dh_params, dhfile);
	if (ret != 0)
	{
		rb_lib_log("rb_setup_ssl_server: failed to parse DH parameters '%s': -0x%x", dhfile, -ret);
		return 0;
	}

	ret = mbedtls_ssl_conf_dh_param_ctx(&sctx->config, &sctx->dh_params);
	if (ret != 0)
	{
		rb_lib_log("rb_setup_ssl_server: failed to set DH parameters on SSL config context: -0x%x", -ret);
		return 0;
	}

	if (&sctx->x509.next)
		mbedtls_ssl_conf_ca_chain(&sctx->config, sctx->x509.next, NULL);
	
	mbedtls_ssl_conf_ca_chain(&sctx->config, &sctx->cacert, NULL);

	if ((ret = mbedtls_ssl_conf_own_cert(&sctx->config, &sctx->x509, &sctx->serv_pk)) != 0)
	{
		rb_lib_log("rb_setup_ssl_server: failed to set up own certificate: -0x%x", -ret);
		return 0;
	}

	return sctx;
}
Esempio n. 29
0
rb_ssl_ctx *
rb_setup_ssl_server(const char *cacert, const char *cert, const char *keyfile, const char *dhfile,
		    const char *ssl_cipher_list, const char *named_curve, rb_tls_ver_t tls_min_ver)
{
        const char *libratbox_data = "libratbox tls session";
	const char *ciphers = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL";
	unsigned long err;
	rb_ssl_ctx *sctx; 
	long tls_opts;
	sctx = rb_malloc(sizeof(rb_ssl_ctx));
	sctx->refcount = 1;
	sctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
	if(sctx->ssl_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s",
			   ERR_error_string(ERR_get_error(), NULL));
		rb_free(sctx);
		return NULL;
	}

	tls_opts = SSL_CTX_get_options(sctx->ssl_ctx);
	/* Disable SSLv2, make the client use our settings */
	tls_opts |= SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION | SSL_OP_CIPHER_SERVER_PREFERENCE;
	switch(tls_min_ver)
	{
		case RB_TLS_VER_SSL3: /* we default to SSLv3..sadly */
			break;
			
		case RB_TLS_VER_TLS1:
#ifdef SSL_OP_NO_SSLv3
			tls_opts |= SSL_OP_NO_SSLv3;
#endif
			break;
		case RB_TLS_VER_TLS1_1:
#ifdef SSL_OP_NO_TLSv1
			tls_opts |= SSL_OP_NO_TLSv1;
#endif
			break;

		case RB_TLS_VER_TLS1_2:
#ifdef SSL_OP_NO_TLSv1
			tls_opts |= SSL_OP_NO_TLSv1;
#endif
#ifdef SSL_OP_NO_TLSv1_1
			tls_opts |= SSL_OP_NO_TLSv1_1;
#endif
			break;
		case RB_TLS_VER_LAST:
			break;
	}

#ifdef SSL_OP_SINGLE_DH_USE
	tls_opts |= SSL_OP_SINGLE_DH_USE;
#endif

#ifdef SSL_OP_SINGLE_ECDH_USE
	tls_opts |= SSL_OP_SINGLE_ECDH_USE;
#endif

#ifdef SSL_OP_NO_TICKET
	tls_opts |= SSL_OP_NO_TICKET;
#endif

	SSL_CTX_set_options(sctx->ssl_ctx, tls_opts);


	if(ssl_cipher_list != NULL)
		ciphers = ssl_cipher_list;

	if(!SSL_CTX_set_cipher_list(sctx->ssl_ctx, ciphers))
	{
		rb_lib_log("rb_setup_ssl_server: Error setting ssl_cipher_list=\"%s\": %s",
			   ciphers, ERR_error_string(ERR_get_error(), NULL));
		goto cleanup;;
	}


	if(cert == NULL)
	{
		rb_lib_log("rb_setup_ssl_server: No certificate file");
		goto cleanup;
	}
	if(!SSL_CTX_use_certificate_chain_file(sctx->ssl_ctx, cert))
	{
		err = ERR_get_error();
		rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", cert,
			   ERR_error_string(err, NULL));
		goto cleanup;
	}
	
	if(cacert != NULL)
	{
		if (!SSL_CTX_load_verify_locations(sctx->ssl_ctx, cacert, NULL)) 
		{
			err = ERR_get_error();
			rb_lib_log("rb_setup_ssl_server: Error loading CA file [%s]: %s", cacert, ERR_error_string(err, NULL));
			goto cleanup;
		}
	}

	if(keyfile == NULL)
	{
		rb_lib_log("rb_setup_ssl_server: No key file");
		goto cleanup;
	}


	if(!SSL_CTX_use_PrivateKey_file(sctx->ssl_ctx, keyfile, SSL_FILETYPE_PEM))
	{
		err = ERR_get_error();
		rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile,
			   ERR_error_string(err, NULL));
		goto cleanup;;
	}


	if(dhfile != NULL)
	{
		/* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */
		BIO *bio = BIO_new_file(dhfile, "r");
		if(bio != NULL)
		{
			DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
			if(dh == NULL)
			{
				err = ERR_get_error();
				rb_lib_log
					("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
					 dhfile, ERR_error_string(err, NULL));
				BIO_free(bio);
				goto cleanup;
			}
			BIO_free(bio);
			SSL_CTX_set_tmp_dh(sctx->ssl_ctx, dh);
			DH_free(dh);
		}
		else
		{
			err = ERR_get_error();
			rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
				   dhfile, ERR_error_string(err, NULL));
			goto cleanup;	  
		}
	}

#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
	
	if(named_curve != NULL)
	{
		int nid;
		EC_KEY *ecdh;
		
		nid = OBJ_sn2nid(named_curve);
		if(nid == 0)
		{
			err = ERR_get_error();
			rb_lib_log("rb_setup_ssl_server: Unknown curve named [%s]: %s", named_curve, ERR_error_string(err, NULL));
			goto cleanup;
		}
		
		ecdh = EC_KEY_new_by_curve_name(nid);
		if(ecdh == NULL)
		{
			err = ERR_get_error();
			rb_lib_log("rb_setup_ssl_server: Curve creation failed for [%s]: %s", named_curve, ERR_error_string(err, NULL));
			goto cleanup;
		}
		SSL_CTX_set_options(sctx->ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
		SSL_CTX_set_tmp_ecdh(sctx->ssl_ctx, ecdh);
		EC_KEY_free(ecdh);
	}
#endif
#endif
	SSL_CTX_set_verify(sctx->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
	SSL_CTX_set_session_id_context(sctx->ssl_ctx, (const unsigned char *)libratbox_data, strlen(libratbox_data));
	return sctx;

cleanup:
	SSL_CTX_free(sctx->ssl_ctx);
	rb_free(sctx);
	return NULL;
		
	
}
Esempio n. 30
0
int
rb_select_epoll(long delay)
{
	int num, i, flags, old_flags, op;
	struct epoll_event ep_event;
	int o_errno;
	void *data;

	num = epoll_wait(ep_info->ep, ep_info->pfd, ep_info->pfd_size, delay);

	/* save errno as rb_set_time() will likely clobber it */
	o_errno = errno;
	rb_set_time();
	errno = o_errno;

	if(num < 0 && !rb_ignore_errno(o_errno))
		return RB_ERROR;

	if(num <= 0)
		return RB_OK;

	for(i = 0; i < num; i++)
	{
		PF *hdl;
		rb_fde_t *F = ep_info->pfd[i].data.ptr;
		old_flags = F->pflags;
		if(ep_info->pfd[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR))
		{
			hdl = F->read_handler;
			data = F->read_data;
			F->read_handler = NULL;
			F->read_data = NULL;
			if(hdl)
			{
				hdl(F, data);
			}
		}

		if(!IsFDOpen(F))
			continue;
		if(ep_info->pfd[i].events & (EPOLLOUT | EPOLLHUP | EPOLLERR))
		{
			hdl = F->write_handler;
			data = F->write_data;
			F->write_handler = NULL;
			F->write_data = NULL;

			if(hdl)
			{
				hdl(F, data);
			}
		}

		if(!IsFDOpen(F))
			continue;

		flags = 0;

		if(F->read_handler != NULL)
			flags |= EPOLLIN;
		if(F->write_handler != NULL)
			flags |= EPOLLOUT;

		if(old_flags != flags)
		{
			if(flags == 0)
				op = EPOLL_CTL_DEL;
			else
				op = EPOLL_CTL_MOD;
			F->pflags = ep_event.events = flags;
			ep_event.data.ptr = F;
			if(op == EPOLL_CTL_MOD || op == EPOLL_CTL_ADD)
				ep_event.events |= EPOLLET;

			if(epoll_ctl(ep_info->ep, op, F->fd, &ep_event) != 0)
			{
				rb_lib_log("rb_select_epoll(): epoll_ctl failed: %s",
					   strerror(errno));
			}
		}

	}
	return RB_OK;
}