Exemplo n.º 1
0
bool cert_VerifySubjectAltName(const CERTCertificate *cert, const char *name)
{
	SECStatus rv;
	SECItem	subAltName;
	PLArenaPool *arena = NULL;
	CERTGeneralName *nameList = NULL;
	CERTGeneralName *current = NULL;
	bool san_ip = FALSE;
	unsigned int len = strlen(name);
	ip_address myip;

	rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME,
			&subAltName);
	if (rv != SECSuccess) {
		DBG(DBG_X509, DBG_log("certificate contains no subjectAltName extension"));
		return FALSE;
	}

	if (tnatoaddr(name, 0, AF_UNSPEC, &myip) == NULL)
		san_ip = TRUE;

	arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
	passert(arena != NULL);

	nameList = current = CERT_DecodeAltNameExtension(arena, &subAltName);
	passert(current != NULL);

	do
	{
		switch (current->type) {
		case certDNSName:
		case certRFC822Name:
			if (san_ip)
				break;
			if (current->name.other.len == len) {
				if (memcmp(current->name.other.data, name, len) == 0) {
					DBG(DBG_X509, DBG_log("subjectAltname %s found in certificate", name));
					PORT_FreeArena(arena, PR_FALSE);
					return TRUE;
				}
			}

			if (current->name.other.len != 0 && current->name.other.len < IDTOA_BUF) {
				char osan[IDTOA_BUF];

				memcpy(osan,current->name.other.data, current->name.other.len);
				osan[current->name.other.len] = '\0';
				DBG(DBG_X509, DBG_log("subjectAltname (len=%d) %s not match %s", current->name.other.len, osan, name));
			} else {
				DBG(DBG_X509, DBG_log("subjectAltname <TOO BIG TO PRINT> does not match %s", name));
			}
			break;

		case certIPAddress:
			if (!san_ip)
				break;
			if ((current->name.other.len == 4) && (addrtypeof(&myip) == AF_INET)) {
				if (memcmp(current->name.other.data, &myip.u.v4.sin_addr.s_addr, 4) == 0) {
					DBG(DBG_X509, DBG_log("subjectAltname IPv4 matches %s", name));
					PORT_FreeArena(arena, PR_FALSE);
					return TRUE;
				} else {
					DBG(DBG_X509, DBG_log("subjectAltname IPv4 does not match %s", name));
					break;
				}
			}
			if ((current->name.other.len == 16) && (addrtypeof(&myip) == AF_INET6)) {
				if (memcmp(current->name.other.data, &myip.u.v6.sin6_addr.s6_addr, 16) == 0) {
					DBG(DBG_X509, DBG_log("subjectAltname IPv6 matches %s", name));
					PORT_FreeArena(arena, PR_FALSE);
					return TRUE;
				} else {
					DBG(DBG_X509, DBG_log("subjectAltname IPv6 does not match %s", name));
					break;
				}
			}
			DBG(DBG_X509, DBG_log("subjectAltnamea IP address family mismatch for %s", name));
			break;

		default:
			break;
		}
		current = CERT_GetNextGeneralName(current);
	} while (current != nameList);

	loglog(RC_LOG_SERIOUS, "No matching subjectAltName found");
	/* Don't free nameList, it's part of the arena. */
	PORT_FreeArena(arena, PR_FALSE);
	return FALSE;
}
Exemplo n.º 2
0
/*
 * See if left->addr or left->next is %defaultroute and change it to IP.
 *
 * Returns:
 * -1: failure
 *  0: done
 *  1: please call again: more to do
 */
static int resolve_defaultroute_one(struct starter_end *host,
				struct starter_end *peer)
{
	/*
	 * "left="         == host->addrtype and host->addr
	 * "leftnexthop="  == host->nexttype and host->nexthop
	 */

	/* What kind of result are we seeking? */
	bool seeking_src = (host->addrtype == KH_DEFAULTROUTE);
	bool seeking_gateway = (host->nexttype == KH_DEFAULTROUTE);

	char msgbuf[RTNL_BUFSIZE];
	bool has_dst = FALSE;
	int query_again = 0;

	if (!seeking_src && !seeking_gateway)
		return 0;	/* this end already figured out */

	/* Fill netlink request */
	netlink_query_init(msgbuf, host->addr_family);
	if (host->nexttype == KH_IPADDR) {
		/*
		 * My nexthop (gateway) is specified.
		 * We need to figure out our source IP to get there.
		 */
		netlink_query_add(msgbuf, RTA_DST, &host->nexthop);
		has_dst = TRUE;
	} else if (peer->addrtype == KH_IPADDR) {
		/*
		 * Peer IP is specified.
		 * We may need to figure out source IP
		 * and gateway IP to get there.
		 */
		netlink_query_add(msgbuf, RTA_DST, &peer->addr);
		has_dst = TRUE;
		if (seeking_src && seeking_gateway &&
			host->addr_family == AF_INET) {
			/*
			 * If we have only peer IP and no gateway/src we must
			 * do two queries:
			 * 1) find out gateway for dst
			 * 2) find out src for that gateway
			 * Doing both in one query returns src for dst.
			 *
			 * (IPv6 returns link-local for gateway so we can and
			 * do seek both in one query.)
			 */
			seeking_src = FALSE;
			query_again = 1;
		}
	}
	if (has_dst && host->addrtype == KH_IPADDR) {
		/* SRC works only with DST */
		netlink_query_add(msgbuf, RTA_SRC, &host->addr);
	}

	/*
	 * If we have for example host=%defaultroute + peer=%any
	 * (no destination) the netlink reply will be full routing table.
	 * We must do two queries:
	 * 1) find out default gateway
	 * 2) find out src for that default gateway
	 */
	if (!has_dst) {
		if (seeking_src && seeking_gateway) {
			seeking_src = FALSE;
			query_again = 1;
		}
	}
	if (seeking_gateway) {
		struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf;

		nlmsg->nlmsg_flags |= NLM_F_DUMP;
        }

	if (verbose)
		printf("\nseeking_src = %d, seeking_gateway = %d, has_dst = %d\n",
			seeking_src, seeking_gateway, has_dst);

	/* Send netlink get_route request */

	ssize_t len = netlink_query(msgbuf);

	if (len < 0)
		return -1;

	/* Parse reply */
	struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf;

	for (; NLMSG_OK(nlmsg, len); nlmsg = NLMSG_NEXT(nlmsg, len)) {
		struct rtmsg *rtmsg;
		struct rtattr *rtattr;
		int rtlen;
		char r_interface[IF_NAMESIZE+1];
		char r_source[ADDRTOT_BUF];
		char r_gateway[ADDRTOT_BUF];
		char r_destination[ADDRTOT_BUF];
		bool ignore;

		if (nlmsg->nlmsg_type == NLMSG_DONE)
			break;

		if (nlmsg->nlmsg_type == NLMSG_ERROR) {
			printf("netlink error\n");
			return -1;
			break;
		}

		/* ignore all but IPv4 and IPv6 */
		rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg);
		if (rtmsg->rtm_family != AF_INET &&
			rtmsg->rtm_family != AF_INET6)
			continue;

		/* Parse one route entry */
		r_interface[0] = r_interface[IF_NAMESIZE] = r_source[0] =
			r_gateway[0] = r_destination[0] = '\0';
		rtattr = (struct rtattr *) RTM_RTA(rtmsg);
		rtlen = RTM_PAYLOAD(nlmsg);
		for (;
			RTA_OK(rtattr, rtlen);
			rtattr = RTA_NEXT(rtattr, rtlen)) {
			switch (rtattr->rta_type) {
			case RTA_OIF:
				if_indextoname(*(int *)RTA_DATA(rtattr),
					r_interface);
				break;

			case RTA_PREFSRC:
				inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr),
					r_source, sizeof(r_source));
				break;

			case RTA_GATEWAY:
				inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr),
					r_gateway, sizeof(r_gateway));
				break;

			case RTA_DST:
				inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr),
					r_destination,
					sizeof(r_destination));
				break;
			}
		}

		/*
		 * Ignore if not main table.
		 * Ignore ipsecX or mastX interfaces.
		 */
		ignore = rtmsg->rtm_table != RT_TABLE_MAIN ||
			startswith(r_interface, "ipsec") ||
			startswith(r_interface, "mast");

		if (verbose) {
			printf("dst %s via %s dev %s src %s table %d%s\n",
				r_destination,
				r_gateway,
				r_interface,
				r_source, rtmsg->rtm_table,
				ignore ? "" : " (ignored)");
		}

		if (ignore)
			continue;

		if (seeking_src && r_source[0] != '\0') {
			err_t err = tnatoaddr(r_source, 0, rtmsg->rtm_family,
					&host->addr);

			if (err == NULL) {
				host->addrtype = KH_IPADDR;
				seeking_src = FALSE;
				if (verbose)
					printf("set addr: %s\n", r_source);
			} else if (verbose) {
				printf("unknown source results from kernel (%s): %s\n",
					r_source, err);
			}
		}

		if (seeking_gateway && r_destination[0] == '\0' &&
			(has_dst || r_source[0] == '\0')) {
			if (r_gateway[0] == '\0' && r_interface[0] != '\0') {
				/*
				 * Point-to-Point default gw without "via IP"
				 * Attempt to find r_gateway as the IP address
				 * on the interface.
				 */
				resolve_ppp_peer(r_interface, host->addr_family,
						 r_gateway);
			}
			if (r_gateway[0] != '\0') {
				err_t err = tnatoaddr(r_gateway, 0,
						rtmsg->rtm_family,
						&host->nexthop);

				if (err != NULL) {
					printf("unknown gateway results from kernel: %s\n",
						err);
				} else {
					/* Note: Use first even if multiple */
					host->nexttype = KH_IPADDR;
					seeking_gateway = FALSE;
					if (verbose)
						printf("set nexthop: %s\n",
							r_gateway);
				}
			}
		}
	}
	return query_again;
}
Exemplo n.º 3
0
static bool validate_end(struct ub_ctx *dnsctx ,
#endif
			struct starter_conn *conn_st,
			struct starter_end *end,
			const char *leftright,
			bool resolvip UNUSED,
			err_t *perr)
{
	err_t er = NULL;
	char *err_str = NULL;
	int family = conn_st->options[KBF_CONNADDRFAMILY];
	bool err = FALSE;

#  define ERR_FOUND(...) { err |= error_append(&err_str, __VA_ARGS__); }

	if (!end->options_set[KNCF_IP])
		conn_st->state = STATE_INCOMPLETE;

	end->addrtype = end->options[KNCF_IP];
	end->addr_family = family;

	/* validate the KSCF_IP/KNCF_IP */
	switch (end->addrtype) {
	case KH_ANY:
		anyaddr(family, &(end->addr));
		break;

	case KH_IFACE:
		/* generally, this doesn't show up at this stage */
		starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_IFACE", leftright);
		break;

	case KH_IPADDR:
		assert(end->strings[KSCF_IP] != NULL);

		if (end->strings[KSCF_IP][0] == '%') {
			pfree(end->iface);
			end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface");
			if (!starter_iface_find(end->iface, family,
					       &end->addr,
					       &end->nexthop))
				conn_st->state = STATE_INVALID;
			/* not numeric, so set the type to the iface type */
			end->addrtype = KH_IFACE;
			break;
		}

		er = ttoaddr_num(end->strings[KNCF_IP], 0, family,
				    &(end->addr));
		if (er != NULL) {
			/* not numeric, so set the type to the string type */
			end->addrtype = KH_IPHOSTNAME;
		}

		if (end->id == NULL) {
			ipstr_buf b;

			end->id = clone_str(ipstr(&end->addr, &b), "end if");
		}
		break;

	case KH_OPPO:
		conn_st->policy |= POLICY_OPPORTUNISTIC;
		break;

	case KH_OPPOGROUP:
		conn_st->policy |= POLICY_OPPORTUNISTIC | POLICY_GROUP;
		break;

	case KH_GROUP:
		conn_st->policy |= POLICY_GROUP;
		break;

	case KH_IPHOSTNAME:
		/* generally, this doesn't show up at this stage */
		starter_log(LOG_LEVEL_DEBUG,
			    "starter: %s is KH_IPHOSTNAME", leftright);
		break;

	case KH_DEFAULTROUTE:
		starter_log(LOG_LEVEL_DEBUG,
			    "starter: %s is KH_DEFAULTROUTE", leftright);
		break;

	case KH_NOTSET:
		starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_NOTSET", leftright);
		break;
	}

	/* validate the KSCF_SUBNET */
	if (end->strings_set[KSCF_SUBNET]) {
		char *value = end->strings[KSCF_SUBNET];

		if (end->strings_set[KSCF_ADDRESSPOOL]) {
			ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=", leftright,
				leftright);
		}

		if (startswith(value, "vhost:") || startswith(value, "vnet:")) {
			er = NULL;
			end->virt = clone_str(value, "validate_end item");
		} else {
			end->has_client = TRUE;
			er = ttosubnet(value, 0, family, &(end->subnet));
		}
		if (er != NULL)
			ERR_FOUND("bad subnet %ssubnet=%s [%s]", leftright,
				  value, er);
	}

	/* set nexthop address to something consistent, by default */
	anyaddr(family, &end->nexthop);
	anyaddr(addrtypeof(&end->addr), &end->nexthop);

	/* validate the KSCF_NEXTHOP */
	if (end->strings_set[KSCF_NEXTHOP]) {
		char *value = end->strings[KSCF_NEXTHOP];

		if (strcaseeq(value, "%defaultroute")) {
			end->nexttype = KH_DEFAULTROUTE;
		} else {
			if (tnatoaddr(value, strlen(value), AF_INET,
				      &(end->nexthop)) != NULL &&
			    tnatoaddr(value, strlen(value), AF_INET6,
				      &(end->nexthop)) != NULL) {
#ifdef DNSSEC
				starter_log(LOG_LEVEL_DEBUG,
					    "Calling unbound_resolve() for %snexthop value",
					    leftright);
				if (!unbound_resolve(dnsctx, value,
						strlen(value), AF_INET,
						&(end->nexthop)) &&
				    !unbound_resolve(dnsctx, value,
						strlen(value), AF_INET6,
						&(end->nexthop)))
					ERR_FOUND("bad value for %snexthop=%s\n",
						leftright, value);
#else
				er = ttoaddr(value, 0, family,
						&(end->nexthop));
				if (er != NULL)
					ERR_FOUND("bad value for %snexthop=%s [%s]",
						leftright, value,
						er);
#endif
			}
			end->nexttype = KH_IPADDR;
		}
	} else {
#if 0
		if (conn_st->policy & POLICY_OPPORTUNISTIC)
			end->nexttype = KH_DEFAULTROUTE;
#endif
		anyaddr(family, &end->nexthop);

		if (end->addrtype == KH_DEFAULTROUTE) {
			end->nexttype = KH_DEFAULTROUTE;
		}
	}

	/* validate the KSCF_ID */
	if (end->strings_set[KSCF_ID]) {
		char *value = end->strings[KSCF_ID];

		pfreeany(end->id);
		end->id = clone_str(value, "end->id");
	}

	if (end->options_set[KSCF_RSAKEY1]) {
		end->rsakey1_type = end->options[KSCF_RSAKEY1];
		end->rsakey2_type = end->options[KSCF_RSAKEY2];

		switch (end->options[KSCF_RSAKEY1]) {
		case PUBKEY_DNS:
		case PUBKEY_DNSONDEMAND:
			end->key_from_DNS_on_demand = TRUE;
			break;

		default:
			end->key_from_DNS_on_demand = FALSE;
			/* validate the KSCF_RSAKEY1/RSAKEY2 */
			if (end->strings[KSCF_RSAKEY1] != NULL) {
				char *value = end->strings[KSCF_RSAKEY1];

				pfreeany(end->rsakey1);
				end->rsakey1 = (unsigned char *)clone_str(value,"end->rsakey1");
			}
			if (end->strings[KSCF_RSAKEY2] != NULL) {
				char *value = end->strings[KSCF_RSAKEY2];

				pfreeany(end->rsakey2);
				end->rsakey2 = (unsigned char *)clone_str(value,"end->rsakey2");
			}
		}
	}

	/* validate the KSCF_SOURCEIP, if any, and if set,
	 * set the subnet to same value, if not set.
	 */
	if (end->strings_set[KSCF_SOURCEIP]) {
		char *value = end->strings[KSCF_SOURCEIP];

		if (tnatoaddr(value, strlen(value), AF_INET,
			      &(end->sourceip)) != NULL &&
		    tnatoaddr(value, strlen(value), AF_INET6,
			      &(end->sourceip)) != NULL) {
#ifdef DNSSEC
			starter_log(LOG_LEVEL_DEBUG,
				    "Calling unbound_resolve() for %ssourceip value",
				    leftright);
			if (!unbound_resolve(dnsctx, value,
					strlen(value), AF_INET,
					&(end->sourceip)) &&
			    !unbound_resolve(dnsctx, value,
					strlen(value), AF_INET6,
					&(end->sourceip)))
				ERR_FOUND("bad value for %ssourceip=%s\n",
					  leftright, value);
#else
			er = ttoaddr(value, 0, family, &(end->sourceip));
			if (er != NULL)
				ERR_FOUND("bad addr %ssourceip=%s [%s]",
					  leftright, value, er);
#endif
		} else {
			er = tnatoaddr(value, 0, family, &(end->sourceip));
			if (er != NULL)
				ERR_FOUND("bad numerical addr %ssourceip=%s [%s]",
					leftright, value, er);
		}
		if (!end->has_client) {
			starter_log(LOG_LEVEL_INFO,
				    "%ssourceip= used but not %ssubnet= defined, defaulting %ssubnet to %s",
				    leftright, leftright, leftright, value);
			er = addrtosubnet(&end->sourceip, &end->subnet);
			if (er != NULL) {
				ERR_FOUND("attempt to default %ssubnet from %s failed: %s",
					leftright, value, er);
			}
			end->has_client = TRUE;
			end->has_client_wildcard = FALSE;
		}
	}

	/* copy certificate path name */
	if (end->strings_set[KSCF_CERT])
		end->cert = clone_str(end->strings[KSCF_CERT], "KSCF_CERT");

	if (end->strings_set[KSCF_CA])
		end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA");

	if (end->strings_set[KSCF_UPDOWN])
		end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN");

	if (end->strings_set[KSCF_PROTOPORT]) {
		err_t ugh;
		char *value = end->strings[KSCF_PROTOPORT];

		ugh = ttoprotoport(value, 0, &end->protocol, &end->port,
				   &end->has_port_wildcard);

		if (ugh != NULL)
			ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value,
				  ugh);
	}

	if (end->strings_set[KSCF_ADDRESSPOOL]) {
		char *addresspool = end->strings[KSCF_ADDRESSPOOL];

		if (end->strings_set[KSCF_SUBNET])
			ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=",
				leftright, leftright);
		starter_log(LOG_LEVEL_DEBUG,
			    "connection's  %saddresspool set to: %s",
			    leftright, end->strings[KSCF_ADDRESSPOOL] );

		er = ttorange(addresspool, 0, AF_INET, &end->pool_range, TRUE);
		if (er != NULL)
			ERR_FOUND("bad %saddresspool=%s [%s]", leftright,
					addresspool, er);
	}

	if (end->options_set[KNCF_XAUTHSERVER] ||
	    end->options_set[KNCF_XAUTHCLIENT])
		conn_st->policy |= POLICY_XAUTH;

	/*
	   KSCF_SUBNETWITHIN    --- not sure what to do with it.
	   KSCF_ESPENCKEY       --- todo (manual keying)
	   KSCF_ESPAUTHKEY      --- todo (manual keying)
	   KSCF_SOURCEIP     = 16,
	   KSCF_MAX          = 19
	 */

	if (err)
		*perr = err_str;
	return err;
#  undef ERR_FOUND
}
Exemplo n.º 4
0
/*
 * See if left->addr or left->next is %defaultroute and change it to IP.
 */
int resolve_defaultroute_one(struct starter_end *left,
			     struct starter_end *right)
{
    /* TODO: this will probably not work with Point-to-Point links */

    /* "left="         == left->addrtype + left->addr
     * "leftnexthop="  == left->nexttype + left->nexthop
     */

    /* What kind of result we want to parse? */
    int parse_src = (left->addrtype == KH_DEFAULTROUTE);
    int parse_gateway = (left->nexttype == KH_DEFAULTROUTE);
    if (parse_src == 0 && parse_gateway == 0)
	return 0;

    /* Fill netlink request */
    char msgbuf[RTNL_BUFSIZE];
    int has_dst = 0;
    netlink_query_init(msgbuf, left->addr_family);
    if (left->nexttype == KH_IPADDR) { /* My nexthop is specified */
	netlink_query_add(msgbuf, RTA_DST, &left->nexthop);
	has_dst = 1;
    } else if (right->addrtype == KH_IPADDR) { /* Peer IP is specified */
	netlink_query_add(msgbuf, RTA_DST, &right->addr);
	has_dst = 1;
    }
    if (has_dst && left->addrtype == KH_IPADDR) /* SRC works only with DST */
	netlink_query_add(msgbuf, RTA_SRC, &left->addr);

    /* If we have for example left=%defaultroute + right=%any, the netlink
     * reply will be full routing table. We just want default gateway for the
     * first run.
     */
    if (has_dst == 0) {
	struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf;
	nlmsg->nlmsg_flags |= NLM_F_DUMP;
        if (parse_gateway)
	    parse_src = 0;
    }
    if (verbose)
	printf("\nparse_src = %d, parse_gateway = %d, has_dst = %d\n",
	       parse_src, parse_gateway, has_dst);

    /* Send netlink get_route request */
    int len = netlink_query(msgbuf);
    if (len < 0)
	return -1;

    /* Parse reply */
    struct nlmsghdr *nlmsg = (struct nlmsghdr *)msgbuf;
    for (; NLMSG_OK(nlmsg, len); nlmsg = NLMSG_NEXT(nlmsg, len)) {
	struct rtmsg *rtmsg;
	struct rtattr *rtattr;
	int rtlen;
	char r_interface[IF_NAMESIZE];
	char r_source[ADDRTOT_BUF];
	char r_gateway[ADDRTOT_BUF];
	char r_destination[ADDRTOT_BUF];

	/* Check for IPv4 / IPv6 */
	rtmsg = (struct rtmsg *) NLMSG_DATA(nlmsg);
	if (rtmsg->rtm_family != AF_INET &&
	    rtmsg->rtm_family != AF_INET6)
	    continue;

	/* Parse one route entry */
	*r_interface = *r_source = *r_gateway = *r_destination = 0;
	rtattr = (struct rtattr *) RTM_RTA(rtmsg);
	rtlen = RTM_PAYLOAD(nlmsg);
	for (; RTA_OK(rtattr, rtlen); rtattr = RTA_NEXT(rtattr, rtlen)) {
	    switch (rtattr->rta_type) {
	    case RTA_OIF:
		if_indextoname(*(int *)RTA_DATA(rtattr), r_interface);
		break;

	    case RTA_PREFSRC:
		inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr),
			  r_source, sizeof(r_source));
		break;

	    case RTA_GATEWAY:
		inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr),
			  r_gateway, sizeof(r_gateway));
		break;

	    case RTA_DST:
		inet_ntop(rtmsg->rtm_family, RTA_DATA(rtattr),
			  r_destination, sizeof(r_destination));
		break;
	    }
	}
	if (verbose)
	    printf("dst %s via %s dev %s src %s\n",
		   r_destination, r_gateway, r_interface, r_source);

	err_t err;
	if (parse_src && *r_source != 0) {
	    err = tnatoaddr(r_source, 0, rtmsg->rtm_family, &left->addr);
	    if (err == NULL) {
		left->addrtype = KH_IPADDR;
		parse_src = 0;
		if (verbose)
		    printf("set addr: %s\n", r_source);
	    } else if (verbose)
		printf("unknown source results from kernel: %s\n", err);
	}
	if (parse_gateway && *r_gateway != 0 && (has_dst || *r_source == 0)) {
	    err = tnatoaddr(r_gateway, 0, rtmsg->rtm_family, &left->nexthop);
	    if (err == NULL) {
		left->nexttype = KH_IPADDR;
		parse_gateway = 0; /* Use first if multiple */
		if (verbose)
		    printf("set nexthop: %s\n", r_gateway);
	    } else if (verbose)
		printf("unknown gateway results from kernel: %s\n", err);
	}
    }

    /* If we parsed and found default_gateway, we must do the request again
     * to find out the source IP for that gateway.
     */
    return has_dst == 0 && parse_gateway == 0;
}
Exemplo n.º 5
0
/* synchronous blocking resolving - simple replacement of ttoaddr()
 * src_len 0 means "apply strlen"
 * af 0 means "try both families
 */
int unbound_resolve(struct ub_ctx *dnsctx, char *src, size_t srclen, int af, ip_address *ipaddr)
{
	const int qtype = (af == AF_INET6) ? 28 : 1; /* 28 = AAAA record, 1 = A record */
	struct ub_result *result;

	passert(dnsctx != NULL);

        if (srclen == 0) {
                srclen = strlen(src);
                if (srclen == 0) {
                        libreswan_log("empty hostname in host lookup\n");
			ub_resolve_free(result);
			return 0;
		}
	}

	{
	  int ugh = ub_resolve(dnsctx, src, qtype, 1 /* CLASS IN */, &result);
	  if(ugh != 0) {
		libreswan_log("unbound error: %s", ub_strerror(ugh));
		ub_resolve_free(result);
		return 0;
	  }
	}

	if(result->bogus) {
		libreswan_log("ERROR: %s failed DNSSEC valdation!\n", result->qname);
		ub_resolve_free(result);
		return 0;
	}
	if(!result->havedata) {
		if(result->secure) {
			DBG(DBG_DNS,DBG_log("Validated reply proves '%s' does not exist\n", src));
		} else {
			DBG(DBG_DNS,DBG_log("Failed to resolve '%s' (%s)\n", src, (result->bogus) ? "BOGUS" : "insecure"));
		}
		ub_resolve_free(result);
		return 0;
	
	} else if(!result->bogus) {
		if(!result->secure) {
			DBG(DBG_DNS,DBG_log("warning: %s lookup was not protected by DNSSEC!\n", result->qname));
		}
	}
	
#if 0
		{
		int i = 0;
		DBG_log("The result has:\n");
		DBG_log("qname: %s\n", result->qname);
		DBG_log("qtype: %d\n", result->qtype);
		DBG_log("qclass: %d\n", result->qclass);
		if(result->canonname)
			DBG_log("canonical name: %s\n", result->canonname);
		DBG_log("DNS rcode: %d\n", result->rcode);

		for(i=0; result->data[i] != NULL; i++) {
			DBG_log("result data element %d has length %d\n",
				i, result->len[i]);
		}
		DBG_log("result has %d data element(s)\n", i);
		}
#endif


	/* XXX: for now pick the first one and return that */
	passert(result->data[0] != NULL);
	{
	   char dst[INET6_ADDRSTRLEN];
	   err_t err = tnatoaddr(inet_ntop(af, result->data[0], dst
			, (af==AF_INET) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN)
			, 0, af, ipaddr);
	   ub_resolve_free(result);
	   if(err == NULL) {
		DBG(DBG_DNS,DBG_log("success for %s lookup", (af==AF_INET) ? "IPv4" : "IPv6"));
		return 1;
	   } else {
		libreswan_log("tnatoaddr failed in unbound_resolve()");
		return 0;
	   }
	}
}
Exemplo n.º 6
0
/**
 * Validate that yes in fact we are one side of the tunnel
 *
 * The function checks that IP addresses are valid, nexthops are
 * present (if needed) as well as policies, and sets the leftID
 * from the left= if it isn't set.
 *
 * @param conn_st a connection definition
 * @param end a connection end
 * @param left boolean (are we 'left'? 1 = yes, 0 = no)
 * @param perr pointer to char containing error value
 * @return bool TRUE if failed
 */
static bool validate_end(struct starter_conn *conn_st
			, struct starter_end *end
			, bool left
			, bool resolvip UNUSED
			, err_t *perr)
{
    err_t er = NULL;
    char *err_str = NULL;
    const char *leftright=(left ? "left" : "right");
    int family = conn_st->options[KBF_CONNADDRFAMILY];
    bool err = FALSE;

#define ERR_FOUND(args...) do { err += error_append(&err_str, ##args); } while(0)

    if(!end->options_set[KNCF_IP]) {
	conn_st->state = STATE_INCOMPLETE;
    }

    end->addrtype=end->options[KNCF_IP];
    end->addr_family = family;

    /* validate the KSCF_IP/KNCF_IP */
    switch(end->addrtype) {
    case KH_ANY:
	anyaddr(family, &(end->addr));
	break;

    case KH_IFACE:
	/* generally, this doesn't show up at this stage */

	break;

    case KH_IPADDR:
        /* right=/left= */
	assert(end->strings[KSCF_IP] != NULL);

	if (end->strings[KSCF_IP][0]=='%') {
	    if (end->iface) pfree(end->iface);
            end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface");
	    if (starter_iface_find(end->iface, family, &(end->addr),
				   &(end->nexthop)) == -1) {
	        conn_st->state = STATE_INVALID;
	    }
	    /* not numeric, so set the type to the iface type */
	    end->addrtype = KH_IFACE;
	    break;
	}

        er = ttoaddr_num(end->strings[KNCF_IP], 0, family, &(end->addr));
	if(er) {
	    /* not numeric, so set the type to the string type */
	    end->addrtype = KH_IPHOSTNAME;
	}

        if(end->id == NULL) {
            char idbuf[ADDRTOT_BUF];
            addrtot(&end->addr, 0, idbuf, sizeof(idbuf));

            end->id= clone_str(idbuf, "end id");
        }
	break;

    case KH_OPPO:
	conn_st->policy |= POLICY_OPPO;
	break;

    case KH_OPPOGROUP:
	conn_st->policy |= POLICY_OPPO|POLICY_GROUP;
	break;

    case KH_GROUP:
	conn_st->policy |= POLICY_GROUP;
	break;

    case KH_IPHOSTNAME:
        /* XXX */
	break;

    case KH_DEFAULTROUTE:
	break;

    case KH_NOTSET:
	break;
    }

    /* validate the KSCF_SUBNET */
    if(end->strings_set[KSCF_SUBNET])
    {
	char *value = end->strings[KSCF_SUBNET];

        if ( ((strlen(value)>=6) && (strncmp(value,"vhost:",6)==0)) ||
	     ((strlen(value)>=5) && (strncmp(value,"vnet:",5)==0)) ) {
	    er = NULL;
	    end->virt = clone_str(value, "end->virt");
	}
	else {
	    end->has_client = TRUE;
	    er = ttosubnet(value, 0, 0, &(end->subnet));
	}
	if (er) ERR_FOUND("bad subnet %ssubnet=%s [%s] family=%s", leftright, value, er, family2str(family));
    }

    /* set nexthop address to something consistent, by default */
    anyaddr(family, &end->nexthop);
    anyaddr(addrtypeof(&end->addr), &end->nexthop);

    /* validate the KSCF_NEXTHOP */
    if(end->strings_set[KSCF_NEXTHOP])
    {
	char *value = end->strings[KSCF_NEXTHOP];

	if(strcasecmp(value, "%defaultroute")==0) {
	    end->nexttype=KH_DEFAULTROUTE;
	} else {
            if (tnatoaddr(value, strlen(value), AF_INET,
                          &(end->nexthop)) != NULL &&
                tnatoaddr(value, strlen(value), AF_INET6,
                          &(end->nexthop)) != NULL) {
                er = ttoaddr(value, 0, family, &(end->nexthop));
                if (er) ERR_FOUND("bad addr %snexthop=%s [%s]", leftright, value, er);
            }
            end->nexttype = KH_IPADDR;
	}
    } else {
      if (end->addrtype == KH_DEFAULTROUTE) {
        end->nexttype = KH_DEFAULTROUTE;
      }
      anyaddr(family, &end->nexthop);
    }

    /* validate the KSCF_ID */
    if(end->strings_set[KSCF_ID])
    {
	char *value = end->strings[KSCF_ID];

        pfreeany(end->id);
        end->id = clone_str(value, "end->id");
    }

    if(end->options_set[KSCF_RSAKEY1]) {
	end->rsakey1_type = end->options[KSCF_RSAKEY1];
	end->rsakey2_type = end->options[KSCF_RSAKEY2];

	switch(end->rsakey1_type) {
	case PUBKEY_DNS:
	case PUBKEY_DNSONDEMAND:
	    end->key_from_DNS_on_demand = TRUE;
	    break;

	default:
	    end->key_from_DNS_on_demand = FALSE;
	    /* validate the KSCF_RSAKEY1/RSAKEY2 */
	    if(end->strings[KSCF_RSAKEY1] != NULL)
	    {
		char *value = end->strings[KSCF_RSAKEY1];

                pfreeany(end->rsakey1);
                end->rsakey1 = (unsigned char *)clone_str(value,"end->rsakey1");
	    }
	    if(end->strings[KSCF_RSAKEY2] != NULL)
	    {
		char *value = end->strings[KSCF_RSAKEY2];

                pfreeany(end->rsakey2);
                end->rsakey2 = (unsigned char *)clone_str(value,"end->rsakey2");
	    }
	}
    }

    /* validate the KSCF_SOURCEIP, if any, and if set,
     * set the subnet to same value, if not set.
     */
    if(end->strings_set[KSCF_SOURCEIP])
    {
	char *value = end->strings[KSCF_SOURCEIP];

	if (tnatoaddr(value, strlen(value), AF_INET, &(end->sourceip)) != NULL
	    && tnatoaddr(value, strlen(value), AF_INET6, &(end->sourceip)) != NULL) {

	    er = ttoaddr(value, 0, 0, &(end->sourceip));
	    if (er) ERR_FOUND("bad addr %ssourceip=%s [%s]", leftright, value, er);

	} else {
		er = tnatoaddr(value, 0, 0, &(end->sourceip));
		if (er) ERR_FOUND("bad numerical addr %ssourceip=%s [%s]", leftright, value, er);
	}

	if(!end->has_client) {
	    starter_log(LOG_LEVEL_INFO, "defaulting %ssubnet to %s\n", leftright, value);
	    er = addrtosubnet(&end->sourceip, &end->subnet);
	    if (er) ERR_FOUND("attempt to default %ssubnet from %s failed: %s", leftright, value, er);
	    end->has_client = TRUE;
	    end->has_client_wildcard = FALSE;
	}
    }

    /* copy certificate path name */
    if(end->strings_set[KSCF_CERT]) {
        end->cert = clone_str(end->strings[KSCF_CERT], "KSCF_CERT");
    }

    if(end->strings_set[KSCF_CA]) {
        end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA");
    }

    if(end->strings_set[KSCF_UPDOWN]) {
        end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN");
    }

    if(end->strings_set[KSCF_PROTOPORT]) {
	err_t ugh;
	char *value = end->strings[KSCF_PROTOPORT];

	ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &end->has_port_wildcard);

	if (ugh) ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value, ugh);
    }

    if (end->options_set[KNCF_XAUTHSERVER] ||
        end->options_set[KNCF_XAUTHCLIENT]) {
	conn_st->policy |= POLICY_XAUTH;
    }

    /*
    KSCF_SUBNETWITHIN    --- not sure what to do with it.
    KSCF_ESPENCKEY       --- todo (manual keying)
    KSCF_ESPAUTHKEY      --- todo (manual keying)
    KSCF_SOURCEIP     = 16,
    KSCF_MAX          = 19
    */

    if(err) *perr = err_str;
    return err;
#  undef ERR_FOUND
}