Exemplo n.º 1
0
bool node_write_devclass(meshlink_handle_t *mesh, node_t *n) {

	if(n->devclass < 0 || n->devclass > _DEV_CLASS_MAX)
		return false;

	bool result = false;

	splay_tree_t *config_tree;
	init_configuration(&config_tree);

	// ignore read errors; in case the file does not exist we will create it
	read_host_config(mesh, config_tree, n->name);

	config_t* cnf = lookup_config(config_tree, "DeviceClass");

	if(!cnf)
	{
		cnf = new_config();
		cnf->variable = xstrdup("DeviceClass");
		config_add(config_tree, cnf);
	}

	set_config_int(cnf, n->devclass);

	if(!write_host_config(mesh, config_tree, n->name))
		goto fail;

	result = true;

fail:
	exit_configuration(&config_tree);
	return result;
}
Exemplo n.º 2
0
bool read_ecdsa_public_key(meshlink_handle_t *mesh, connection_t *c) {
	if(ecdsa_active(c->ecdsa))
		return true;

	char *p;

	if(!c->config_tree) {
		init_configuration(&c->config_tree);
		if(!read_host_config(mesh, c->config_tree, c->name))
			return false;
	}

	/* First, check for simple ECDSAPublicKey statement */

	if(get_config_string(lookup_config(c->config_tree, "ECDSAPublicKey"), &p)) {
		c->ecdsa = ecdsa_set_base64_public_key(p);
		free(p);
		return c->ecdsa;
	}

	return false;
}
Exemplo n.º 3
0
bool node_read_ecdsa_public_key(meshlink_handle_t *mesh, node_t *n) {
	if(ecdsa_active(n->ecdsa))
		return true;

	splay_tree_t *config_tree;
	char *p;

	init_configuration(&config_tree);
	if(!read_host_config(mesh, config_tree, n->name))
		goto exit;

	/* First, check for simple ECDSAPublicKey statement */

	if(get_config_string(lookup_config(config_tree, "ECDSAPublicKey"), &p)) {
		n->ecdsa = ecdsa_set_base64_public_key(p);
		free(p);
	}

exit:
	exit_configuration(&config_tree);
	return n->ecdsa;
}
Exemplo n.º 4
0
bool node_read_devclass(meshlink_handle_t *mesh, node_t *n) {
	
	splay_tree_t *config_tree;
	char *p;

	init_configuration(&config_tree);
	if(!read_host_config(mesh, config_tree, n->name))
		goto exit;

	if(get_config_string(lookup_config(config_tree, "DeviceClass"), &p))
	{
		n->devclass = atoi(p);
		free(p);
	}

	if(n->devclass < 0 || n->devclass > _DEV_CLASS_MAX)
		{ n->devclass = _DEV_CLASS_MAX; }

exit:
	exit_configuration(&config_tree);
	return n->devclass != 0;
}
Exemplo n.º 5
0
bool id_h(connection_t *c, const char *request) {
	char name[MAX_STRING_SIZE];

	if(sscanf(request, "%*d " MAX_STRING " %d.%d", name, &c->protocol_major, &c->protocol_minor) < 2) {
		logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ID", c->name,
			   c->hostname);
		return false;
	}

	/* Check if this is a control connection */

	if(name[0] == '^' && !strcmp(name + 1, controlcookie)) {
		c->status.control = true;
		c->allow_request = CONTROL;
		c->last_ping_time = now.tv_sec + 3600;

		free(c->name);
		c->name = xstrdup("<control>");

		return send_request(c, "%d %d %d", ACK, TINC_CTL_VERSION_CURRENT, getpid());
	}

	if(name[0] == '?') {
		if(!invitation_key) {
			logger(DEBUG_ALWAYS, LOG_ERR, "Got invitation from %s but we don't have an invitation key", c->hostname);
			return false;
		}

		c->ecdsa = ecdsa_set_base64_public_key(name + 1);
		if(!c->ecdsa) {
			logger(DEBUG_ALWAYS, LOG_ERR, "Got bad invitation from %s", c->hostname);
			return false;
		}

		c->status.invitation = true;
		char *mykey = ecdsa_get_base64_public_key(invitation_key);
		if(!mykey)
			return false;
		if(!send_request(c, "%d %s", ACK, mykey))
			return false;
		free(mykey);

		c->protocol_minor = 2;

		return sptps_start(&c->sptps, c, false, false, invitation_key, c->ecdsa, "tinc invitation", 15, send_meta_sptps, receive_invitation_sptps);
	}

	/* Check if identity is a valid name */

	if(!check_id(name)) {
		logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ID", c->name,
			   c->hostname, "invalid name");
		return false;
	}

	/* If this is an outgoing connection, make sure we are connected to the right host */

	if(c->outgoing) {
		if(strcmp(c->name, name)) {
			logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s is %s instead of %s", c->hostname, name,
				   c->name);
			return false;
		}
	} else {
		if(c->name)
			free(c->name);
		c->name = xstrdup(name);
	}

	/* Check if version matches */

	if(c->protocol_major != myself->connection->protocol_major) {
		logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s (%s) uses incompatible version %d.%d",
			c->name, c->hostname, c->protocol_major, c->protocol_minor);
		return false;
	}

	if(bypass_security) {
		if(!c->config_tree)
			init_configuration(&c->config_tree);
		c->allow_request = ACK;
		return send_ack(c);
	}

	if(!experimental)
		c->protocol_minor = 0;

	if(!c->config_tree) {
		init_configuration(&c->config_tree);

		if(!read_host_config(c->config_tree, c->name)) {
			logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s had unknown identity (%s)", c->hostname, c->name);
			return false;
		}

		if(experimental)
			read_ecdsa_public_key(c);
			/* Ignore failures if no key known yet */
	}

	if(c->protocol_minor && !ecdsa_active(c->ecdsa))
		c->protocol_minor = 1;

	/* Forbid version rollback for nodes whose Ed25519 key we know */

	if(ecdsa_active(c->ecdsa) && c->protocol_minor < 2) {
		logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s (%s) tries to roll back protocol version to %d.%d",
			c->name, c->hostname, c->protocol_major, c->protocol_minor);
		return false;
	}

	c->allow_request = METAKEY;

	if(c->protocol_minor >= 2) {
		c->allow_request = ACK;
		char label[25 + strlen(myself->name) + strlen(c->name)];

		if(c->outgoing)
			snprintf(label, sizeof label, "tinc TCP key expansion %s %s", myself->name, c->name);
		else
			snprintf(label, sizeof label, "tinc TCP key expansion %s %s", c->name, myself->name);

		return sptps_start(&c->sptps, c, c->outgoing, false, myself->connection->ecdsa, c->ecdsa, label, sizeof label, send_meta_sptps, receive_meta_sptps);
	} else {
		return send_metakey(c);
	}
}
Exemplo n.º 6
0
/*
  Configure node_t mesh->self and set up the local sockets (listen only)
*/
bool setup_myself(meshlink_handle_t *mesh) {
	char *name;
	char *address = NULL;

	if(!(name = get_name(mesh))) {
		logger(mesh, MESHLINK_ERROR, "Name for MeshLink instance required!");
		return false;
	}

	mesh->self = new_node();
	mesh->self->connection = new_connection();
	mesh->self->name = name;
	mesh->self->devclass = mesh->devclass;
	mesh->self->connection->name = xstrdup(name);
	read_host_config(mesh, mesh->config, name);

	if(!get_config_string(lookup_config(mesh->config, "Port"), &mesh->myport)) {
		logger(mesh, MESHLINK_ERROR, "Port for MeshLink instance required!");
		return false;
	}

	mesh->self->connection->options = 0;
	mesh->self->connection->protocol_major = PROT_MAJOR;
	mesh->self->connection->protocol_minor = PROT_MINOR;

	mesh->self->options |= PROT_MINOR << 24;

	if(!read_ecdsa_private_key(mesh))
		return false;

	/* Ensure mesh->myport is numeric */

	if(!atoi(mesh->myport)) {
		struct addrinfo *ai = str2addrinfo("localhost", mesh->myport, SOCK_DGRAM);
		sockaddr_t sa;
		if(!ai || !ai->ai_addr)
			return false;
		free(mesh->myport);
		memcpy(&sa, ai->ai_addr, ai->ai_addrlen);
		sockaddr2str(&sa, NULL, &mesh->myport);
	}

	/* Check some options */

	if(!setup_myself_reloadable(mesh))
		return false;

	/* Compression */

	// TODO: drop compression in the packet layer?
	mesh->self->incompression = 0;
	mesh->self->connection->outcompression = 0;

	/* Done */

	mesh->self->nexthop = mesh->self;
	mesh->self->via = mesh->self;
	mesh->self->status.reachable = true;
	mesh->self->last_state_change = mesh->loop.now.tv_sec;

	node_write_devclass(mesh, mesh->self);
	node_add(mesh, mesh->self);

	graph(mesh);

	load_all_nodes(mesh);

	/* Open sockets */

	mesh->listen_sockets = 0;

	if(!add_listen_address(mesh, address, NULL))
		return false;

	if(!mesh->listen_sockets) {
		logger(mesh, MESHLINK_ERROR, "Unable to create any listening socket!");
		return false;
	}

	xasprintf(&mesh->self->hostname, "MYSELF port %s", mesh->myport);
	mesh->self->connection->hostname = xstrdup(mesh->self->hostname);

	/* Done. */

	mesh->last_config_check = mesh->loop.now.tv_sec;

	return true;
}