ProtocolError DTLSMessageChannel::command(Command command, void* arg)
{
	DEBUG("session command: %d", command);
	switch (command)
	{
	case CLOSE:
		reset_session();
		break;

	case DISCARD_SESSION:
		reset_session();
		return IO_ERROR; //force re-establish

	case MOVE_SESSION:
		move_session = true;
		break;

	case LOAD_SESSION:
		sessionPersist.restore(callbacks.restore);
		break;

	case SAVE_SESSION:
		sessionPersist.save(callbacks.save);
		break;
	}
	return NO_ERROR;
}
ProtocolError DTLSMessageChannel::send(Message& message)
{
  if (ssl_context.state != MBEDTLS_SSL_HANDSHAKE_OVER)
    return INVALID_STATE;

  if (message.send_direct())
  {
	  // send unencrypted
	  int bytes = this->send(message.buf(), message.length());
	  return bytes < 0 ? IO_ERROR : NO_ERROR;
  }

#ifdef DEBUG_BUILD
      LOG(TRACE, "message length %d", message.length());
      for (size_t i=0; i<message.length(); i++)
      {
	  	  char buf[3];
	  	  char c = message.buf()[i];
	  	  sprintf(buf, "%02x", c);
	  	  LOG_PRINT(TRACE, buf);
      }
      LOG_PRINT(TRACE, "\n");
#endif

  int ret = mbedtls_ssl_write(&ssl_context, message.buf(), message.length());
  if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
  {
	  reset_session();
	  return IO_ERROR;
  }
  sessionPersist.update(&ssl_context, callbacks.save, coap_state ? *coap_state : 0);
  return NO_ERROR;
}
Exemplo n.º 3
0
static int tee_open(struct inode *inode, struct file *filp)
{
	struct tee_session *ts;
	filp->private_data = kmalloc(sizeof(struct tee_session),
				     GFP_KERNEL);

	if (filp->private_data == NULL) {
		pr_err(TEED_PFX "[%s] allocation failed", __func__);
		return -ENOMEM;
	}

	ts = (struct tee_session *)(filp->private_data);
	reset_session(ts);

	return 0;
}
Exemplo n.º 4
0
static void handle_close_cancel_session(server *srv, connection *con,
		void *plugindata)
{
	plugin_data *p = (plugin_data *)plugindata;

	if (copy_bits_session_id_or_set_error(srv, con))
		return;
	if (set_error_if_request_has_content(srv, con))
		return;

	char uuid_str[UUID_STR_LEN];
	uuid_unparse(p->session_id, uuid_str);
	DEBUGLOG("ss", "Ending session", uuid_str);

	reset_session(p);
	bits_remove_session(srv, con);
}
ProtocolError DTLSMessageChannel::receive(Message& message)
{
	if (ssl_context.state != MBEDTLS_SSL_HANDSHAKE_OVER)
		return INVALID_STATE;

	create(message);
	uint8_t* buf = message.buf();
	size_t len = message.capacity();

	conf.read_timeout = 0;
	int ret = mbedtls_ssl_read(&ssl_context, buf, len);
	if (ret<0) {
		switch (ret) {
		case MBEDTLS_ERR_SSL_WANT_READ:
			break;
		case MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE:
			ret = 0;
			break;
		case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
			command(CLOSE);
			break;
		default:
			reset_session();
			return IO_ERROR;
		}
	}
	message.set_length(ret);
	if (ret>0) {
		cancel_move_session();
#if defined(DEBUG_BUILD) && 0
		if (LOG_ENABLED(TRACE)) {
		  LOG(TRACE, "message length %d", message.length());
		  for (size_t i=0; i<message.length(); i++)
		  {
				  char buf[3];
				  char c = message.buf()[i];
				  sprintf(buf, "%02x", c);
				  LOG_PRINT(TRACE, buf);
		  }
		  LOG_PRINT(TRACE, "\n");
		}
#endif
	}
	return NO_ERROR;
}
Exemplo n.º 6
0
int teec_open_session(struct tee_context *context,
		      struct tee_session *session,
		      const struct tee_uuid *destination,
		      unsigned int connection_method,
		      void *connection_data, struct tee_operation *operation,
		      unsigned int *error_origin)
{
	int res = TEED_SUCCESS;

	if (session == NULL || destination == NULL) {
		pr_err(TEED_PFX "[%s] session or destination == NULL\n",
		       __func__);
		if (error_origin != NULL)
			*error_origin = TEED_ORIGIN_DRIVER;
		res = TEED_ERROR_BAD_PARAMETERS;
		goto exit;
	}

	reset_session(session);

	/*
	 * Open a session towards an application already loaded inside
	 * the TEE.
	 */
	session->uuid = kmalloc(sizeof(struct tee_uuid), GFP_KERNEL);

	if (session->uuid == NULL) {
		pr_err(TEED_PFX "[%s] error, out of memory (uuid)\n",
		       __func__);
		if (error_origin != NULL)
			*error_origin = TEED_ORIGIN_DRIVER;
		res = TEED_ERROR_OUT_OF_MEMORY;
		goto exit;
	}

	memcpy(session->uuid, destination, sizeof(struct tee_uuid));

	session->ta = NULL;
	session->id = 0;

exit:
	return res;
}
Exemplo n.º 7
0
static void handle_create_session(server *srv, connection *con,
		void *plugindata)
{
        plugin_data *data = (plugin_data *)plugindata;

	if (!uuid_is_null(data->session_id)) {
		DEBUGLOG("s", "Session changed");
		reset_session(data);
	}

	uuid_generate(data->session_id);
	bits_create_session(srv, con, data->session_id);

	if (data->conf.sparse) {
		DEBUGLOG("s", "Backend target is sparse");
		data->state.backend_sparse = 1;
	} else {
		data->state.zero_unalloc = 1;
	}
}
ProtocolError DTLSMessageChannel::establish(uint32_t& flags, uint32_t app_state_crc)
{
	int ret = 0;
	INFO("establish");
	ProtocolError error = setup_context();
	if (error) {
		INFO("setup_contex error %x", error);
		return error;
	}
	bool renegotiate = false;

	SessionPersist::RestoreStatus restoreStatus = sessionPersist.restore(&ssl_context, renegotiate, keys_checksum, coap_state, callbacks.restore);
	DEBUG("restoreStatus = %d", restoreStatus);
	if (restoreStatus==SessionPersist::COMPLETE)
	{
		DEBUG("out_ctr %d,%d,%d,%d,%d,%d,%d,%d, next_coap_id=%d", sessionPersist.out_ctr[0],
				sessionPersist.out_ctr[1],sessionPersist.out_ctr[2],sessionPersist.out_ctr[3],
				sessionPersist.out_ctr[4],sessionPersist.out_ctr[5],sessionPersist.out_ctr[6],
				sessionPersist.out_ctr[7], sessionPersist.next_coap_id);
		sessionPersist.make_persistent();
		uint32_t actual = sessionPersist.application_state_checksum(this->callbacks.calculate_crc);
		DEBUG("application state checksum: %x, expected: %x", actual, app_state_crc);
		if (actual==app_state_crc) {
			DEBUG("skipping sending hello message");
			flags |= Protocol::SKIP_SESSION_RESUME_HELLO;
		}
		DEBUG("restored session from persisted session data. next_msg_id=%d", *coap_state);
		return SESSION_RESUMED;
	}
	else if (restoreStatus==SessionPersist::RENEGOTIATE)
	{
		// session partially restored, fully restored via handshake
	}
	else // no session or clear
	{
		reset_session();
		ProtocolError error = setup_context();
		if (error)
			return error;
	}
	uint8_t random[64];

	do
	{
		while (ssl_context.state != MBEDTLS_SSL_HANDSHAKE_OVER)
		{
			ret = mbedtls_ssl_handshake_step(&ssl_context);

			if (ret != 0)
				break;

			// we've already received the ServerHello, thus
			// we have the random values for client and server
			if (ssl_context.state == MBEDTLS_SSL_SERVER_KEY_EXCHANGE)
			{
				memcpy(random, ssl_context.handshake->randbytes, 64);
			}
		}
	}
	while(ret == MBEDTLS_ERR_SSL_WANT_READ ||
	      ret == MBEDTLS_ERR_SSL_WANT_WRITE);

	if (ret)
	{
		DEBUG("handshake failed -%x", -ret);
		reset_session();
	}
	else
	{
		sessionPersist.prepare_save(random, keys_checksum, &ssl_context, 0);
	}
	return ret==0 ? NO_ERROR : IO_ERROR;
}
Exemplo n.º 9
0
/* Handle the connection of a client.
 */
static void connection_handler(t_session *session) {
	int result;
#ifdef ENABLE_SSL
	t_ssl_accept_data sad;
#endif

#ifdef ENABLE_DEBUG
	session->current_task = "thread started";
#endif

#ifdef ENABLE_SSL
	if (session->binding->use_ssl) {
		sad.context         = &(session->ssl_context);
		sad.client_fd       = &(session->client_socket);
		sad.private_key     = session->binding->private_key;
		sad.certificate     = session->binding->certificate;
		sad.ca_certificate  = session->binding->ca_certificate;
		sad.ca_crl          = session->binding->ca_crl;

		sad.timeout         = session->kept_alive == 0 ? session->binding->time_for_1st_request : session->binding->time_for_request;
		sad.min_ssl_version = session->config->min_ssl_version;
		sad.dh_size         = session->config->dh_size;
#ifdef ENABLE_DEBUG
		sad.thread_id       = session->thread_id;
		session->current_task = "ssl accept";
#endif
		switch (ssl_accept(&sad)) {
			case SSL_HANDSHAKE_NO_MATCH:
				log_system(session, "No cypher overlap during SSL handshake.");
				break;
			case SSL_HANDSHAKE_TIMEOUT:
				handle_timeout(session);
				break;
			case SSL_HANDSHAKE_OKE:
				session->socket_open = true;
				break;
		}
	} else
#endif
		session->socket_open = true;

	if (session->socket_open) {
#ifdef ENABLE_MONITOR
		if (session->config->monitor_enabled) {
			monitor_count_connection(session);
		}
#endif

		do {
			result = serve_client(session);
			handle_request_result(session, result);
#ifdef ENABLE_TOMAHAWK
			if (session->parsing_oke) {
				show_request_to_admins(session->method, session->request_uri, session->http_version, &(session->ip_address),
				                       session->http_headers, session->return_code, session->bytes_sent);
			}
#endif

#ifdef ENABLE_DEBUG
			session->current_task = "request done";
#endif

			if (session->socket_open) {
				/* Flush the output-buffer
				 */
				if (send_buffer(session, NULL, 0) == -1) {
					session->keep_alive = false;
				}
			}

#ifdef ENABLE_MONITOR
			if (session->config->monitor_enabled) {
				monitor_count_host(session);
			}
#endif
			reset_session(session);
#ifdef ENABLE_DEBUG
			session->current_task = "session reset";
#endif

			if ((session->kept_alive > 0) && (session->config->ban_on_flooding > 0)) {
				if (client_is_flooding(session)) {
					if (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny) {
						ban_ip(&(session->ip_address), session->config->ban_on_flooding, session->config->kick_on_ban);
						log_system(session, "Client banned because of flooding");
						session->keep_alive = false;
#ifdef ENABLE_MONITOR
						if (session->config->monitor_enabled) {
							monitor_count_ban(session);
						}
#endif
					}
				}
			}
		} while (session->keep_alive && session->socket_open);
#ifdef ENABLE_DEBUG
		session->current_task = "session done";
#endif

		destroy_session(session);
		close_socket(session);
	} else {
		close(session->client_socket);
	}

	if (session->config->reconnect_delay > 0) {
		mark_client_for_removal(session, session->config->reconnect_delay);
	} else {
		remove_client(session, true);
	}

#ifdef ENABLE_DEBUG
	/* Show memory usage by thread
	 */
	memdbg_print_log(false);
#endif

	/* Client session ends here
	 */
#ifndef ENABLE_THREAD_POOL
	pthread_exit(NULL);
#endif
}
Exemplo n.º 10
0
/*
 * Called when a process writes to a dev file.
 */
static int tee_write(struct file *filp, const char __user *buffer,
		     size_t length, loff_t *offset)
{
	struct tee_session ku_buffer;
	struct tee_session *ts;
	int ret = 0;

	if (length != sizeof(struct tee_session)) {
		pr_err(TEED_PFX "[%s] error, incorrect input length\n",
		       __func__);
		return -EINVAL;
	}

	if (copy_from_user(&ku_buffer, buffer, length)) {
		pr_err(TEED_PFX "[%s] error, tee_session "
		       "copy_from_user failed\n", __func__);
		return -EINVAL;
	}

	ts = (struct tee_session *)(filp->private_data);

	if (ts == NULL) {
		pr_err(TEED_PFX "[%s] error, private_data not "
		       "initialized\n", __func__);
		return -EINVAL;
	}

	mutex_lock(&sync);

	switch (ts->state) {
	case TEED_STATE_OPEN_DEV:
		ret = open_tee_device(ts, &ku_buffer);
		break;

	case TEED_STATE_OPEN_SESSION:
		switch (ku_buffer.driver_cmd) {
		case TEED_INVOKE:
			ret = invoke_command(ts, &ku_buffer,
					     (struct tee_session *)buffer);
			break;

		case TEED_CLOSE_SESSION:
			/* no caching implemented yet... */
			if (call_sec_world(ts, TEED_CLOSE_SESSION)) {
				set_emsg(ts, TEED_ERROR_COMMUNICATION,
					 __LINE__);
				ret = -EINVAL;
			}

			kfree(ts->ta);
			ts->ta = NULL;

			reset_session(ts);
			break;

		default:
			set_emsg(ts, TEED_ERROR_BAD_PARAMETERS, __LINE__);
			ret = -EINVAL;
		}
		break;
	default:
		pr_err(TEED_PFX "[%s] unknown state\n", __func__);
		set_emsg(ts, TEED_ERROR_BAD_STATE, __LINE__);
		ret = -EINVAL;
	}

	/*
	 * We expect that ret has value zero when reaching the end here.
	 * If it has any other value some error must have occured.
	 */
	if (!ret)
		ret = length;
	else {
		pr_err(TEED_PFX "[%s], forcing error to -EINVAL\n", __func__);
		ret = -EINVAL;
	}

	mutex_unlock(&sync);

	return ret;
}
Exemplo n.º 11
0
/* Handle the connection of a client.
 */
static void connection_handler(t_session *session) {
	int result;
#ifdef ENABLE_SSL
	t_ssl_accept_data sad;
#endif
#ifdef ENABLE_MONITOR
	int connections;

#ifdef ENABLE_DEBUG
	session->current_task = "thread started";
#endif

	connections = ++open_connections;
	if (session->config->monitor_enabled) {
		if (connections > session->config->monitor_stats.simultaneous_connections) {
			session->config->monitor_stats.simultaneous_connections = connections;
		}
	}
#endif

#ifdef ENABLE_SSL
	if (session->binding->use_ssl) {
		sad.context         = &(session->ssl_context);
		sad.client_fd       = &(session->client_socket);
		sad.private_key     = session->binding->private_key;
		sad.certificate     = session->binding->certificate;
		sad.ca_certificate  = session->binding->ca_certificate;
		sad.ca_crl          = session->binding->ca_crl;

		sad.timeout         = session->kept_alive == 0 ? session->binding->time_for_1st_request : session->binding->time_for_request;
		sad.min_ssl_version = session->config->min_ssl_version;
		sad.dh_size         = session->config->dh_size;
#ifdef ENABLE_DEBUG
		session->current_task = "ssl accept";
#endif
		switch (ssl_accept(&sad)) {
			case -2:
				handle_timeout(session);
				break;
			case 0:
				session->socket_open = true;
				break;
		}
	} else
#endif
		session->socket_open = true;

	if (session->socket_open) {
		do {
			result = serve_client(session);
			handle_request_result(session, result);

#ifdef ENABLE_DEBUG
			session->current_task = "request done";
#endif

			if (session->socket_open) {
				send_buffer(session, NULL, 0); /* Flush the output-buffer */
			}

#ifdef ENABLE_MONITOR
			if (session->config->monitor_enabled) {
				monitor_counter_request(session);
				if (session->host->monitor_requests && (result > 0)) {
					monitor_request(session);
				}
			}
#endif
			reset_session(session);
#ifdef ENABLE_DEBUG
			session->current_task = "session reset";
#endif

			if ((session->kept_alive > 0) && (session->config->ban_on_flooding > 0)) {
				if (client_is_flooding(session)) {
					if (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny) {
						ban_ip(&(session->ip_address), session->config->ban_on_flooding, session->config->kick_on_ban);
						log_system(session, "Client banned because of flooding");
						session->keep_alive = false;
#ifdef ENABLE_MONITOR
						if (session->config->monitor_enabled) {
							monitor_counter_ban(session);
						}
#endif
					}
				}
			}
		} while (session->keep_alive && session->socket_open);
#ifdef ENABLE_DEBUG
		session->current_task = "session done";
#endif

		destroy_session(session);
		close_socket(session);
	} else {
		close(session->client_socket);
	}

#ifdef ENABLE_MONITOR
	open_connections--;
#endif

	if (session->config->reconnect_delay > 0) {
		mark_client_for_removal(session, session->config->reconnect_delay);
	} else {
		remove_client(session, true);
	}

	/* Client session ends here
	 */
#ifndef ENABLE_THREAD_POOL
	pthread_exit(NULL);
#endif
}