Пример #1
0
/**
 * Parse "port:IP" string to retrieve the host address and port.
 *
 * @param str		the string to parse
 * @param endptr	if not NULL, it will point the first character after
 * 					the parsed elements.
 * @param port_ptr	where the parsed port is written
 * @param addr_ptr	where the parsed address is written
 *
 * @return TRUE if we parsed the string correctly, FALSE if it did not
 * look like a valid "port:IP" string.
 */
bool
string_to_port_host_addr(const char *str, const char **endptr,
	uint16 *port_ptr, host_addr_t *addr_ptr)
{
	const char *ep;
	host_addr_t addr;
	bool ret;
	uint16 port;
	int error;

	port = parse_uint16(str, &ep, 10, &error);
	if (!error && ':' == *ep) {
		ret = string_to_host_or_addr(ep, &ep, &addr);
		ret = ret && is_host_addr(addr);
	} else {
		addr = zero_host_addr;
		ret = FALSE;
	}

	if (addr_ptr)
		*addr_ptr = addr;
	if (port_ptr)
		*port_ptr = port;
	if (endptr)
		*endptr = ep;

	return ret;
}
Пример #2
0
/**
 * Parse "IP:port" string to retrieve the host address and port.
 *
 * @param str		the string to parse
 * @param endptr	if not NULL, it will point the first character after
 * 					the parsed elements.
 * @param addr_ptr	where the parsed address is written
 * @param port_ptr	where the parsed port is written
 *
 * @return TRUE if we parsed the string correctly, FALSE if it did not
 * look like a valid "IP:port" string.
 */
bool
string_to_host_addr_port(const char *str, const char **endptr,
	host_addr_t *addr_ptr, uint16 *port_ptr)
{
	const char *ep;
	host_addr_t addr;
	bool ret;
	uint16 port;

	ret = string_to_host_or_addr(str, &ep, &addr);
	if (ret && ':' == *ep && is_host_addr(addr)) {
		int error;

		ep++;
		port = parse_uint16(ep, &ep, 10, &error);
		ret = 0 == error && 0 != port;
	} else {
		ret = FALSE;
		port = 0;
	}

	if (addr_ptr)
		*addr_ptr = addr;
	if (port_ptr)
		*port_ptr = port;
	if (endptr)
		*endptr = ep;

	return ret;
}
Пример #3
0
static const char *
magnet_parse_host_port(const char *hostport,
	host_addr_t *addr, uint16 *port, const char **host, const char **host_end,
	const char **error_str)
{
	const char *p;
	const char *endptr;

	clear_error_str(&error_str);
	g_return_val_if_fail(hostport, NULL);

	p = hostport;

	if (!string_to_host_or_addr(p, &endptr, addr)) {
		*error_str = "Expected host part";
		return NULL;
	}

	if (is_host_addr(*addr)) {
		if (host)     *host = NULL;
		if (host_end) *host_end = NULL;
	} else {
		if (host)     *host = p;
		if (host_end) *host_end = endptr;
	}
	p += endptr - p;

	if (':' == *p) {
		const char *ep2;
		int error;
		uint16 u;

		p++;
		u = parse_uint16(p, &ep2, 10, &error);
		if (error) {
			*error_str = "TCP port is out of range";
			/* Skip this parameter */
			return NULL;
		}

		*port = u;
		p += ep2 - p;
	} else {
		*port = 80;
	}

	return p;
}
Пример #4
0
/**
 * Parse hostname:port and return the hostname and port parts.
 *
 * @param hp	host:port string
 * @param host	where the pointer to the hostname is returned (static data)
 * @param port	where the port is written to
 *
 * @return TRUE if we successfully parsed the string.
 */
static bool
uhc_get_host_port(const char *hp, const char **host, uint16 *port)
{
	static char hostname[MAX_HOSTLEN + 1];
	const char *ep;
	uint32 u;
	int error;
	size_t len;
	char *p;

	g_assert(hp);
	g_assert(host);
	g_assert(port);

	*host = NULL;
	*port = 0;
	hostname[0] = '\0';

	if (!string_to_host_or_addr(hp, &ep, NULL) || ':' != *ep)
		return FALSE;

	len = ep - hp;
	if (len >= sizeof hostname)
		return FALSE;
	p = mempcpy(hostname, hp, len);
	*p = '\0';

	g_assert(':' == *ep);
	ep++;

	u = parse_uint32(ep, NULL, 10, &error);
	if (error || u < 1 || u > 0xffff)
		return FALSE;

	*host = hostname;			/* Static data! */
	*port = u;

	return TRUE;
}
Пример #5
0
/**
 * Try to connect to the list of nodes given by in following form:
 *
 * list = <node> | <node>, 1*<node>
 * port = 1..65535
 * hostname = 1*[a-zA-Z0-9.-]
 * node = hostname [":" <port>]
 *       | <IPv4 address>[":" <port>]
 *		 | <IPv6 address>
 *		 | "[" <IPv6 address> "]:" <port>
 * peer = ["tls:"]["g2:"]<node>
 *
 * If the port is omitted, the default port (GTA_PORT: 6346) is used.
 * The case-insensitive prefix "tls:" requests a TLS (encrypted) connection.
 */
void
nodes_gui_common_connect_by_name(const gchar *line)
{
	const gchar *q;

    g_assert(line);

	q = line;
	while ('\0' != *q) {
		const gchar *endptr, *hostname;
		size_t hostname_len;
		host_addr_t addr;
		guint32 flags;
    	guint16 port;
		bool g2;

		q = skip_ascii_spaces(q);
		if (',' == *q) {
			q++;
			continue;
		}

		addr = zero_host_addr;
		port = GTA_PORT;
		flags = SOCK_F_FORCE;
		endptr = NULL;
		hostname = NULL;
		hostname_len = 0;

		endptr = is_strcaseprefix(q, "tls:");
		if (endptr) {
			flags |= SOCK_F_TLS;
			q = endptr;
		}

		endptr = is_strcaseprefix(q, "g2:");
		if (endptr) {
			g2 = TRUE;
			q = endptr;
		} else {
			g2 = FALSE;
		}

		if (!string_to_host_or_addr(q, &endptr, &addr)) {
			g_message("expected hostname or IP address");
			break;
		}

		if (!is_host_addr(addr)) {
			hostname = q;
			hostname_len = endptr - q;
		}

		q = endptr;

		if (':' == *q) {
			gint error;

			port = parse_uint16(&q[1], &endptr, 10, &error);
			if (error || 0 == port) {
				g_message("cannot parse port");
				break;
			}

			q = skip_ascii_spaces(endptr);
		} else {
			q = skip_ascii_spaces(endptr);
			if ('\0' != *q && ',' != *q) {
				g_message("expected \",\" or \":\"");
				break;
			}
		}

		if (!hostname) {
			if (g2) {
				guc_node_g2_add(addr, port, flags);
			} else {
				guc_node_add(addr, port, flags);
			}
		} else {
			struct add_node_context *ctx;
			gchar *p;

			if ('\0' == hostname[hostname_len])	{
				p = NULL;
			} else {
				size_t n = 1 + hostname_len;

				g_assert(n > hostname_len);
				p = halloc(n);
				g_strlcpy(p, hostname, n);
				hostname = p;
			}

			WALLOC(ctx);
			ctx->port = port;
			ctx->flags = flags;
			ctx->g2 = g2;
			guc_adns_resolve(hostname, add_node_helper, ctx);

			HFREE_NULL(p);
		}
	}
}
Пример #6
0
/**
 * Loads the whitelist into memory.
 */
static void G_COLD
whitelist_retrieve(void)
{
	char line[1024];
	FILE *f;
	filestat_t st;
	unsigned linenum = 0;
	file_path_t fp[1];

	whitelist_generation++;

	file_path_set(fp, settings_config_dir(), whitelist_file);
	f = file_config_open_read_norename("Host Whitelist", fp, N_ITEMS(fp));
	if (!f)
		return;

	if (fstat(fileno(f), &st)) {
		g_warning("%s(): fstat() failed: %m", G_STRFUNC);
		fclose(f);
		return;
	}

    while (fgets(line, sizeof line, f)) {
		pslist_t *sl_addr, *sl;
		const char *endptr, *start;
		host_addr_t addr;
    	uint16 port;
		uint8 bits;
		bool item_ok;
		bool use_tls;
		char *hname;

        linenum++;

		if (!file_line_chomp_tail(line, sizeof line, NULL)) {
			g_warning("%s(): line %u too long, aborting", G_STRFUNC, linenum);
			break;
		}

        if (file_line_is_skipable(line))
			continue;

		sl_addr = NULL;
		addr = zero_host_addr;
		endptr = NULL;
		hname = NULL;

		endptr = is_strprefix(line, "tls:");
		if (endptr) {
			use_tls = TRUE;
			start = endptr;
		} else {
			use_tls = FALSE;
			start = line;
		}

		port = 0;
		if (string_to_host_addr_port(start, &endptr, &addr, &port)) {
       		sl_addr = name_to_host_addr(host_addr_to_string(addr),
							settings_dns_net());
		} else if (string_to_host_or_addr(start, &endptr, &addr)) {
			uchar c = *endptr;

			switch (c) {
			case '\0':
			case ':':
			case '/':
				break;
			default:
				if (!is_ascii_space(c))
					endptr = NULL;
			}

			if (!endptr) {
				g_warning("%s(): line %d: "
					"expected a hostname or IP address \"%s\"",
					G_STRFUNC, linenum, line);
				continue;
			}

			/* Terminate the string for name_to_host_addr() */
			hname = h_strndup(start, endptr - start);
		} else {
            g_warning("%s(): line %d: expected hostname or IP address \"%s\"",
				G_STRFUNC, linenum, line);
			continue;
		}

       	g_assert(sl_addr != NULL || hname != NULL);
		g_assert(NULL != endptr);
		bits = 0;
		item_ok = TRUE;

		/*
		 * When an explicit address is given (no hostname) and with no
		 * port, one can suffix the address with bits to indicate a CIDR
		 * range of whitelisted addresses.
		 */

		if (0 == port) {
			/* Ignore trailing items separated by a space */
			while ('\0' != *endptr && !is_ascii_space(*endptr)) {
				uchar c = *endptr++;

				if (':' == c) {
					int error;
					uint32 v;

					if (0 != port) {
						g_warning("%s(): line %d: multiple colons after host",
							G_STRFUNC, linenum);
						item_ok = FALSE;
						break;
					}

					v = parse_uint32(endptr, &endptr, 10, &error);
					port = (error || v > 0xffff) ? 0 : v;
					if (0 == port) {
						g_warning("%s(): line %d: "
							"invalid port value after host",
							G_STRFUNC, linenum);
						item_ok = FALSE;
						break;
					}
				} else if ('/' == c) {
					const char *ep;
					uint32 mask;

					if (0 != bits) {
						g_warning("%s(): line %d: "
							"multiple slashes after host", G_STRFUNC, linenum);
						item_ok = FALSE;
						break;
					}

					if (string_to_ip_strict(endptr, &mask, &ep)) {
						if (!host_addr_is_ipv4(addr)) {
							g_warning("%s(): line %d: "
								"IPv4 netmask after non-IPv4 address",
								G_STRFUNC, linenum);
							item_ok = FALSE;
							break;
						}
						endptr = ep;

						if (0 == (bits = netmask_to_cidr(mask))) {
							g_warning("%s(): line %d: "
								"IPv4 netmask after non-IPv4 address",
								G_STRFUNC, linenum);
							item_ok = FALSE;
							break;
						}

					} else {
						int error;
						uint32 v;

						v = parse_uint32(endptr, &endptr, 10, &error);
						if (
							error ||
							0 == v ||
							(v > 32 && host_addr_is_ipv4(addr)) ||
							(v > 128 && host_addr_is_ipv6(addr))
						) {
							g_warning("%s(): line %d: "
								"invalid numeric netmask after host",
								G_STRFUNC, linenum);
							item_ok = FALSE;
							break;
						}
						bits = v;
					}
				} else {
					g_warning("%s(): line %d: "
						"unexpected character after host", G_STRFUNC, linenum);
					item_ok = FALSE;
					break;
				}
			}
		}

		if (item_ok) {
			struct whitelist *item;
			if (hname) {
				item = whitelist_hostname_create(use_tls, hname, port);
				whitelist_dns_resolve(item, FALSE);
			} else {
				PSLIST_FOREACH(sl_addr, sl) {
					host_addr_t *aptr = sl->data;
					g_assert(aptr != NULL);
					item = whitelist_addr_create(use_tls, *aptr, port, bits);
					whitelist_add(item);
				}
			}
		} else {