Beispiel #1
0
/*
 * Iterate through the allowed_targets_list, and if none of the
 * specified addresses matches the one from REDIRECT
 * payload, return FALSE
 */
static bool allow_to_be_redirected(const char *allowed_targets_list, ip_address *dest_ip)
{
	if (allowed_targets_list == NULL || streq(allowed_targets_list, "%any"))
		return TRUE;

	ip_address ip_addr;

	for (const char *t = allowed_targets_list;; ) {
		t += strspn(t, ", ");	/* skip leading separator */
		int len = strcspn(t, ", ");	/* length of name */
		if (len == 0)
			break;	/* no more */

		err_t ugh = ttoaddr_num(t, len, AF_UNSPEC, &ip_addr);

		if (ugh != NULL) {
			DBGF(DBG_CONTROLMORE, "address %.*s isn't a valid address", len, t);
		} else if (sameaddr(dest_ip, &ip_addr)) {
			DBGF(DBG_CONTROLMORE,
				"address %.*s is a match to received GW identity", len, t);
			return TRUE;
		} else {
			DBGF(DBG_CONTROLMORE,
				"address %.*s is not a match to received GW identity", len, t);
		}
		t += len;	/* skip name */
	}
	DBGF(DBG_CONTROLMORE,
		"we did not find suitable address in the list specified by accept-redirect-to option");
	return FALSE;
}
void block_peer_add(ip_address *ip)
{
    block_peer **cur = &block_peer_head, *tmp;

    if (!block_ip_reject_num)
	return;
    for (; *cur; cur = &(*cur)->next)
    {
	if (!sameaddr(&(*cur)->ip, ip))
	    continue;
	(*cur)->reject_num++;
	(*cur)->last_reject_time = now();
	goto Exit;
    }
    tmp = (block_peer *)malloc(sizeof(block_peer));
    if (!tmp)
	return;
    tmp->reject_num = 1;
    tmp->ip = *ip;
    tmp->start_time = 0;
    tmp->last_reject_time = now();
    tmp->next = NULL;
    *cur = tmp;
    block_peer_log("IP address %s was added to block-IP list", tmp);

Exit:
    block_peer_start_block(*cur);
}
Beispiel #3
0
void
restart_connections_by_peer(struct connection *c)
{
    struct connection *d;

    if (c->host_pair == NULL)
   	   return;

    d = c->host_pair->connections;
    for (; d != NULL; d = d->hp_next) {
	   if (
#ifdef DYNAMICDNS
	       (c->dnshostname && d->dnshostname && (strcmp(c->dnshostname, d->dnshostname) == 0))
	   	|| (c->dnshostname == NULL && d->dnshostname == NULL &&
#endif /* DYNAMICDNS */
		sameaddr(&d->spd.that.host_addr, &c->spd.that.host_addr)
#ifdef DYNAMICDNS
		)
#endif /* DYNAMICDNS */
		)
	       terminate_connection(d->name);
    }

#ifdef DYNAMICDNS
    update_host_pairs(c);
#endif /* DYNAMICDNS */

    if (c->host_pair == NULL)
    	   return;
    d = c->host_pair->connections;
    for (; d != NULL; d = d->hp_next) {
    	   if (
#ifdef DYNAMICDNS
	       (c->dnshostname && d->dnshostname && (strcmp(c->dnshostname, d->dnshostname) == 0))
	   	|| (c->dnshostname == NULL && d->dnshostname == NULL &&
#endif /* DYNAMICDNS */
		sameaddr(&d->spd.that.host_addr, &c->spd.that.host_addr)
#ifdef DYNAMICDNS
		)
#endif /* DYNAMICDNS */
		)
	       initiate_connection(d->name, NULL_FD, 0, pcim_demand_crypto);
    }
}
Beispiel #4
0
/* compare two struct id values */
bool
same_id(const struct id *a, const struct id *b)
{
    a = resolve_myid(a);
    b = resolve_myid(b);

    if(b->kind == ID_NONE || a->kind==ID_NONE) {
	return TRUE;    /* it's the wildcard */
    }

    if (a->kind != b->kind)
	return FALSE;
    
    switch (a->kind)
    {
    case ID_NONE:
	return TRUE;	/* repeat of above for completeness */

    case ID_IPV4_ADDR:
    case ID_IPV6_ADDR:
	return sameaddr(&a->ip_addr, &b->ip_addr);

    case ID_FQDN:
    case ID_USER_FQDN:
	/* assumptions:
	 * - case should be ignored
	 * - trailing "." should be ignored (even if the only character?)
	 */
	{
	    size_t al = a->name.len
		, bl = b->name.len;

	    while (al > 0 && a->name.ptr[al - 1] == '.')
		al--;
	    while (bl > 0 && b->name.ptr[bl - 1] == '.')
		bl--;
	    return al == bl
		&& strncasecmp((char *)a->name.ptr
			       , (char *)b->name.ptr, al) == 0;
	}

    case ID_DER_ASN1_DN:
	return same_dn(a->name, b->name);

    case ID_KEY_ID:
	return a->name.len == b->name.len
	    && memcmp(a->name.ptr, b->name.ptr, a->name.len) == 0;

    default:
	bad_case(a->kind);
    }
    /* NOTREACHED */
    return FALSE;
}
block_peer *block_peer_get_by_ip(ip_address *ip)
{
    block_peer *peer = block_peer_head;

    for (; peer; peer=peer->next)
    {
	if (sameaddr(ip, &peer->ip))
	    return peer;
    }
    return NULL;
}
Beispiel #6
0
/* ipcmp compares the two ip_address values a and b.
 * It returns -1, 0, or +1 if a is, respectively,
 * less than, equal to, or greater than b.
 */
static int ipcmp(ip_address *a, ip_address *b)
{
	if (addrtypeof(a) != addrtypeof(b)) {
		return addrtypeof(a) < addrtypeof(b) ? -1 : 1;
	} else if (sameaddr(a, b)) {
		return 0;
	} else {
		const struct sockaddr *sa = sockaddrof(a),
		*sb = sockaddrof(b);

		passert(addrtypeof(a) == AF_INET); /* not yet implemented IPv6 version :-( */
		return (ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr)
			<
			ntohl(((const struct sockaddr_in *)sb)->sin_addr.s_addr))
		       ?
		       -1 : 1;
	}
}
Beispiel #7
0
void subrange(unsigned char *sin, unsigned char *ein)
// recursive function to divide ip range
{
	unsigned char nets[4], nete[4];
	int bitlen, nextlen;

	bitlen = count_bits(sin, ein);

	if (bitlen == 32) {
		sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/32 ", sin[0], sin[1], sin[2], sin[3]);
		cprintf("%u.%u.%u.%u/32\n", sin[0], sin[1], sin[2], sin[3]);
		return;
	} else if (bitlen == 31) {
		sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/31 ", sin[0], sin[1], sin[2], sin[3]);
		cprintf("%u.%u.%u.%u/31\n", sin[0], sin[1], sin[2], sin[3]);
		return;
	}

	nextlen = bitlen + 1;

	getse(sin, nets, nete, bitlen);

	if (sameaddr(sin, nets) && sameaddr(ein, nete)) {
		sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/%d ", nets[0], nets[1], nets[2], nets[3], bitlen);
		cprintf("%u.%u.%u.%u/%d\n", nets[0], nets[1], nets[2], nets[3], bitlen);
		return;
	}

	getse(sin, nets, nete, nextlen);

	if (sameaddr(sin, nete)) {
		sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/32 ", sin[0], sin[1], sin[2], sin[3]);
		cprintf("%u.%u.%u.%u/32\n", sin[0], sin[1], sin[2], sin[3]);
	} else if (sameaddr(sin, nets)) {
		sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/%d ", nets[0], nets[1], nets[2], nets[3], nextlen);
		cprintf("%u.%u.%u.%u/%d\n", nets[0], nets[1], nets[2], nets[3], nextlen);
	} else			// continue check
		subrange(sin, nete);

	getse(ein, nets, nete, nextlen);

	if (sameaddr(ein, nets)) {
		sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/32 ", ein[0], ein[1], ein[2], ein[3]);
		cprintf("%u.%u.%u.%u/32\n", ein[0], ein[1], ein[2], ein[3]);
	} else if (sameaddr(ein, nete)) {
		sprintf(range_buf + strlen(range_buf), "%u.%u.%u.%u/%d ", nets[0], nets[1], nets[2], nets[3], nextlen);
		cprintf("%u.%u.%u.%u/%d\n", nets[0], nets[1], nets[2], nets[3], nextlen);
	} else			// continue check
		subrange(nets, ein);

}
void block_peer_del(ip_address *ip)
{
    block_peer **peer = &block_peer_head, *tmp;

    while (*peer)
    {
	if (ip && !sameaddr(ip, &(*peer)->ip))
	{
	    peer=&(*peer)->next;
	    continue;
	}
	tmp = *peer;
	*peer = tmp->next;
	block_peer_log("IP address %s was removed from block-IP list", tmp);
	block_peer_free(tmp);
	if (ip)
	    return;
    }
}
Beispiel #9
0
static void
nilwalkfwd(NilFlow *rcheck)
{
	NilFlow *r;
	Prog *p;
	ProgInfo info;
	
	// If the path down from rcheck dereferences the address
	// (possibly with a small offset) before writing to memory
	// and before any subsequent checks, it's okay to wait for
	// that implicit check. Only consider this basic block to
	// avoid problems like:
	//	_ = *x // should panic
	//	for {} // no writes but infinite loop may be considered visible
	for(r = (NilFlow*)uniqs(&rcheck->f); r != nil; r = (NilFlow*)uniqs(&r->f)) {
		p = r->f.prog;
		proginfo(&info, p);
		
		if((info.flags & LeftRead) && smallindir(&p->from, &rcheck->f.prog->from)) {
			rcheck->kill = 1;
			return;
		}
		if((info.flags & (RightRead|RightWrite)) && smallindir(&p->to, &rcheck->f.prog->from)) {
			rcheck->kill = 1;
			return;
		}
		
		// Stop if another nil check happens.
		if(p->as == ACHECKNIL)
			return;
		// Stop if value is lost.
		if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from))
			return;
		// Stop if memory write.
		if((info.flags & RightWrite) && !regtyp(&p->to))
			return;
	}
}
Beispiel #10
0
static void
bsdkame_process_raw_ifaces(struct raw_iface *rifaces)
{
    struct raw_iface *ifp;

    /* 
     * There are no virtual interfaces, so all interfaces are valid
     */
    for (ifp = rifaces; ifp != NULL; ifp = ifp->next)
    {
	bool after = FALSE; /* has vfp passed ifp on the list? */
	bool bad = FALSE;
	struct raw_iface *vfp;

	for (vfp = rifaces; vfp != NULL; vfp = vfp->next)
	{
	    if (vfp == ifp)
	    {
		after = TRUE;
	    }
	    else if (sameaddr(&ifp->addr, &vfp->addr))
	    {
	      if (after)
		{
		  loglog(RC_LOG_SERIOUS
			 , "IP interfaces %s and %s share address %s!"
			 , ifp->name, vfp->name, ip_str(&ifp->addr));
		}
	      bad = TRUE;
	    }
	}

	if (bad)
	    continue;

	/* We've got all we need; see if this is a new thing:
	 * search old interfaces list.
	 */
	{
	    struct iface_port **p = &interfaces;

	    for (;;)
	    {
		struct iface_port *q = *p;
		struct iface_dev *id = NULL;

		/* search is over if at end of list */
		if (q == NULL)
		{
		    /* matches nothing -- create a new entry */
		    int fd = create_socket(ifp, ifp->name, pluto_port);

		    if (fd < 0)
			break;

#ifdef NAT_TRAVERSAL
		    if (nat_traversal_support_non_ike && addrtypeof(&ifp->addr) == AF_INET)
		    {
			nat_traversal_espinudp_socket(fd, "IPv4", ESPINUDP_WITH_NON_IKE);
		    }
#endif

		    q = alloc_thing(struct iface_port, "struct iface_port");
		    id = alloc_thing(struct iface_dev, "struct iface_dev");

		    LIST_INSERT_HEAD(&interface_dev, id, id_entry);

		    q->ip_dev = id;
		    id->id_rname = clone_str(ifp->name, "real device name");
		    id->id_vname = clone_str(ifp->name, "virtual device name");
		    id->id_count++;

		    q->ip_addr = ifp->addr;
		    q->fd = fd;
		    q->next = interfaces;
		    q->change = IFN_ADD;
		    q->port = pluto_port;
		    q->ike_float = FALSE;

		    interfaces = q;

		    openswan_log("adding interface %s/%s %s:%d"
				 , q->ip_dev->id_vname
				 , q->ip_dev->id_rname
				 , ip_str(&q->ip_addr)
				 , q->port);

#ifdef NAT_TRAVERSAL
		    /*
		     * right now, we do not support NAT-T on IPv6, because
		     * the kernel did not support it, and gave an error
		     * it one tried to turn it on.
		     */
		    if (nat_traversal_support_port_floating
			&& addrtypeof(&ifp->addr) == AF_INET)
		    {
			fd = create_socket(ifp, id->id_vname, NAT_T_IKE_FLOAT_PORT);
			if (fd < 0) 
			    break;
			nat_traversal_espinudp_socket(fd, "IPv4"
						      , ESPINUDP_WITH_NON_ESP);
			q = alloc_thing(struct iface_port, "struct iface_port");
			q->ip_dev = id;
			id->id_count++;
			
			q->ip_addr = ifp->addr;
			setportof(htons(NAT_T_IKE_FLOAT_PORT), &q->ip_addr);
			q->port = NAT_T_IKE_FLOAT_PORT;
			q->fd = fd;
			q->next = interfaces;
			q->change = IFN_ADD;
			q->ike_float = TRUE;
			interfaces = q;
			openswan_log("adding interface %s/%s %s:%d"
				     , q->ip_dev->id_vname, q->ip_dev->id_rname
				     , ip_str(&q->ip_addr)
				     , q->port);
		    }
#endif
		    break;
		}

		/* search over if matching old entry found */
		if (streq(q->ip_dev->id_rname, ifp->name)
		    && streq(q->ip_dev->id_vname, ifp->name)
		    && sameaddr(&q->ip_addr, &ifp->addr))
		{
		    /* matches -- rejuvinate old entry */
		    q->change = IFN_KEEP;
#ifdef NAT_TRAVERSAL
		    /* look for other interfaces to keep (due to NAT-T) */
		    for (q = q->next ; q ; q = q->next) {
			if (streq(q->ip_dev->id_rname, ifp->name)
			    && streq(q->ip_dev->id_vname, ifp->name)
			    && sameaddr(&q->ip_addr, &ifp->addr)) {
				q->change = IFN_KEEP;
			}
		    }
#endif
		    break;
		}

		/* try again */
		p = &q->next;
	    } /* for (;;) */
	}
Beispiel #11
0
static void klips_process_raw_ifaces(struct raw_iface *rifaces)
{
	struct raw_iface *ifp;

	/* Find all virtual/real interface pairs.
	 * For each real interface...
	 */
	for (ifp = rifaces; ifp != NULL; ifp = ifp->next) {
		struct raw_iface *v = NULL;     /* matching ipsecX interface */
		struct raw_iface fake_v;
		bool after = FALSE;             /* has vfp passed ifp on the list? */
		bool bad = FALSE;
		struct raw_iface *vfp;
		ip_address lip;

		if (pluto_listen) {
			err_t e;
			e = ttoaddr(pluto_listen, 0, 0, &lip);
			if (e) {
				DBG_log("invalid listen= option ignored: %s\n",
					e);
				pluto_listen = NULL;
			}
		}

		/* ignore if virtual (ipsec*) interface */
		if (strncmp(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX) -
			    1) == 0)
			continue;

		/* ignore if virtual (mast*) interface */
		if (strncmp(ifp->name, MASTDEVPREFIX, sizeof(MASTDEVPREFIX) -
			    1) == 0)
			continue;

		for (vfp = rifaces; vfp != NULL; vfp = vfp->next) {
			if (vfp == ifp) {
				after = TRUE;
			} else if (sameaddr(&ifp->addr, &vfp->addr)) {
				/* Different entries with matching IP addresses.
				 * Many interesting cases.
				 */
				if (strncmp(vfp->name, IPSECDEVPREFIX,
					    sizeof(IPSECDEVPREFIX) - 1) == 0) {
					if (v != NULL) {
						loglog(RC_LOG_SERIOUS,
						       "ipsec interfaces %s and %s share same address %s",
						       v->name, vfp->name,
						       ip_str(&ifp->addr));
						bad = TRUE;
					} else {
						v = vfp; /* current winner */
					}
				} else {
					/* ugh: a second real interface with the same IP address
					 * "after" allows us to avoid double reporting.
					 */
#if defined(linux) && defined(NETKEY_SUPPORT)
					if (kern_interface == USE_NETKEY) {
						if (after) {
							bad = TRUE;
							break;
						}
						continue;
					}
#endif
					if (after) {
						loglog(RC_LOG_SERIOUS,
						       "IP interfaces %s and %s share address %s!",
						       ifp->name, vfp->name,
						       ip_str(&ifp->addr));
					}
					bad = TRUE;
				}
			}
		}

		if (bad)
			continue;

#if defined(linux) && defined(NETKEY_SUPPORT)
		if (kern_interface == USE_NETKEY) {
			v = ifp;
			goto add_entry;
		}
#endif

		/* what if we didn't find a virtual interface? */
		if (v == NULL) {
			if (kern_interface == NO_KERNEL) {
				/* kludge for testing: invent a virtual device */
				static const char fvp[] = "virtual";
				fake_v = *ifp;
				passert(sizeof(fake_v.name) > sizeof(fvp));
				strcpy(fake_v.name, fvp);
				addrtot(&ifp->addr, 0,
					fake_v.name + sizeof(fvp) - 1,
					sizeof(fake_v.name) -
					(sizeof(fvp) - 1));
				v = &fake_v;
			} else {
				DBG(DBG_CONTROL,
				    DBG_log(
					    "IP interface %s %s has no matching ipsec* interface -- ignored",
					    ifp->name, ip_str(&ifp->addr)));
				continue;
			}
		}

		/* ignore if --listen is specified and we do not match */
		if (pluto_listen != NULL) {
			if (!sameaddr(&lip, &ifp->addr)) {
				libreswan_log("skipping interface %s with %s",
					      ifp->name, ip_str(&ifp->addr));
				continue;
			}
		}

		/* We've got all we need; see if this is a new thing:
		 * search old interfaces list.
		 */
#if defined(linux) && defined(NETKEY_SUPPORT)
add_entry:
#endif
		{
			struct iface_port **p = &interfaces;

			for (;; ) {
				struct iface_port *q = *p;
				struct iface_dev *id = NULL;

				/* search is over if at end of list */
				if (q == NULL) {
					/* matches nothing -- create a new entry */
					int fd = create_socket(ifp, v->name,
							       pluto_port);

					if (fd < 0)
						break;

					DBG(DBG_NATT,
					    DBG_log(
						    "NAT-T KLIPS: checking for nat_traversal_support_non_ike for IPv4"));
					if (nat_traversal_support_non_ike &&
					    addrtypeof(&ifp->addr) ==
					    AF_INET) {
						DBG(DBG_NATT,
						    DBG_log(
							    "NAT-T KLIPS: found, calling nat_traversal_espinudp_socket"));
						nat_traversal_espinudp_socket(
							fd, "IPv4",
							ESPINUDP_WITH_NON_IKE);
					} else {
						DBG(DBG_NATT,
						    DBG_log(
							    "NAT-T KLIPS: support not found, nat_traversal_support_non_ike = %s",
							    nat_traversal_support_non_ike
							    ?
							    "TRUE" : "FALSE"));
					}

					q = alloc_thing(struct iface_port,
							"struct iface_port");
					id = alloc_thing(struct iface_dev,
							 "struct iface_dev");

					LIST_INSERT_HEAD(&interface_dev, id,
							 id_entry);

					q->ip_dev = id;
					id->id_rname = clone_str(ifp->name,
								 "real device name");
					id->id_vname = clone_str(v->name,
								 "virtual device name klips");
					id->id_count++;

					q->ip_addr = ifp->addr;
					q->fd = fd;
					q->next = interfaces;
					q->change = IFN_ADD;
					q->port = pluto_port;
					q->ike_float = FALSE;

					interfaces = q;

					libreswan_log(
						"adding interface %s/%s %s:%d",
						q->ip_dev->id_vname,
						q->ip_dev->id_rname,
						ip_str(&q->ip_addr),
						q->port);

					/*
					 * right now, we do not support NAT-T on IPv6, because
					 * the kernel did not support it, and gave an error
					 * it one tried to turn it on.
					 */
					if (nat_traversal_support_port_floating
					    &&
					    addrtypeof(&ifp->addr) ==
					    AF_INET) {
						DBG(DBG_NATT,
						    DBG_log(
							    "NAT-T KLIPS: found floating port, calling nat_traversal_espinudp_socket"));
						fd = create_socket(ifp,
								   v->name,
								   pluto_natt_float_port);
						if (fd < 0)
							break;
						nat_traversal_espinudp_socket(
							fd, "IPv4",
							ESPINUDP_WITH_NON_ESP);
						q = alloc_thing(
							struct iface_port,
							"struct iface_port");
						q->ip_dev = id;
						id->id_count++;

						q->ip_addr = ifp->addr;
						setportof(htons(
								  pluto_natt_float_port),
							  &q->ip_addr);
						q->port =
							pluto_natt_float_port;
						q->fd = fd;
						q->next = interfaces;
						q->change = IFN_ADD;
						q->ike_float = TRUE;
						interfaces = q;
						libreswan_log(
							"adding interface %s/%s %s:%d",
							q->ip_dev->id_vname, q->ip_dev->id_rname,
							ip_str(&q->
							       ip_addr),
							q->port);
					}
					break;
				}

				/* search over if matching old entry found */
				if (streq(q->ip_dev->id_rname, ifp->name) &&
				    streq(q->ip_dev->id_vname, v->name) &&
				    sameaddr(&q->ip_addr, &ifp->addr)) {
					/* matches -- rejuvinate old entry */
					q->change = IFN_KEEP;

					/* look for other interfaces to keep (due to NAT-T) */
					for (q = q->next; q; q = q->next) {
						if (streq(q->ip_dev->id_rname,
							  ifp->name) &&
						    streq(q->ip_dev->id_vname,
							  v->name) &&
						    sameaddr(&q->ip_addr,
							     &ifp->addr))
							q->change = IFN_KEEP;
					}

					break;
				}

				/* try again */
				p = &q->next;
			} /* for (;;) */
		}
Beispiel #12
0
/* compare two struct id values */
bool same_id(const struct id *a, const struct id *b)
{
	a = resolve_myid(a);
	b = resolve_myid(b);

	if (b->kind == ID_NONE || a->kind == ID_NONE) {
		DBG(DBG_PARSING, DBG_log("id type with ID_NONE means wildcard match"));
		return TRUE; /* it's the wildcard */
	}

	if (a->kind != b->kind) {
		return FALSE;
	}

	switch (a->kind) {
	case ID_NONE:
		return TRUE; /* repeat of above for completeness */

	case ID_NULL:
		if (a->kind == b->kind) {
			DBG(DBG_PARSING, DBG_log("ID_NULL: id kind matches"));
			return TRUE;
		}
		return FALSE;

	case ID_IPV4_ADDR:
	case ID_IPV6_ADDR:
		return sameaddr(&a->ip_addr, &b->ip_addr);

	case ID_FQDN:
	case ID_USER_FQDN:
		/*
		 * assumptions:
		 * - case should be ignored
		 * - trailing "." should be ignored
		 *   (even if the only character?)
		 */
	{
		size_t al = a->name.len,
			bl = b->name.len;

		while (al > 0 && a->name.ptr[al - 1] == '.')
			al--;
		while (bl > 0 && b->name.ptr[bl - 1] == '.')
			bl--;
		return al == bl &&
			strncaseeq((char *)a->name.ptr,
				(char *)b->name.ptr, al);
	}

	case ID_FROMCERT:
		DBG(DBG_CONTROL,
			DBG_log("same_id() received ID_FROMCERT - unexpected"));
		/* FALLTHROUGH */
	case ID_DER_ASN1_DN:
		return same_dn(a->name, b->name);

	case ID_KEY_ID:
		return a->name.len == b->name.len &&
			memeq(a->name.ptr, b->name.ptr, a->name.len);

	default:
		bad_case(a->kind);
		/* NOTREACHED */
		return FALSE;
	}
}
Beispiel #13
0
/** returns a host pair based upon addresses.
 *
 * find_host_pair is given a pair of addresses, plus UDP ports, and
 * returns a host_pair entry that covers it. It also moves the relevant
 * pair description to the beginning of the list, so that it can be
 * found faster next time.
 */
struct host_pair *find_host_pair(const ip_address *myaddr,
				 u_int16_t myport,
				 const ip_address *hisaddr,
				 u_int16_t hisport)
{
	struct host_pair *p, *prev;

	/* default hisaddr to an appropriate any */
	if (hisaddr == NULL) {
#if 0
		/* broken */
		const struct af_info *af = aftoinfo(addrtypeof(myaddr));

		if (af == NULL)
			af = aftoinfo(AF_INET);

		if (af)
			hisaddr = af->any;

#else
		hisaddr = aftoinfo(addrtypeof(myaddr))->any;
#endif
	}

	/*
	 * look for a host-pair that has the right set of ports/address.
	 *
	 */

	/*
	 * for the purposes of comparison, port 500 and 4500 are identical,
	 * but other ports are not.
	 * So if any port==4500, then set it to 500.
	 * But we can also have non-RFC values for pluto_port and pluto_nat_port
	 */
	if (myport == pluto_nat_port)
		myport = pluto_port;
	if (hisport == pluto_nat_port)
		hisport = pluto_port;

	for (prev = NULL, p = host_pairs; p != NULL; prev = p, p = p->next) {
		DBG(DBG_CONTROLMORE, {
			ipstr_buf b1;
			ipstr_buf b2;

			DBG_log("find_host_pair: comparing %s:%d to %s:%d",
				ipstr(&p->me.addr, &b1), p->me.host_port,
				ipstr(&p->him.addr, &b2), p->him.host_port);
		    });

		if (sameaddr(&p->me.addr, myaddr) &&
		    (!p->me.host_port_specific || p->me.host_port == myport) &&
		    sameaddr(&p->him.addr, hisaddr) &&
		    (!p->him.host_port_specific || p->him.host_port == hisport)
		    ) {
			if (prev != NULL) {
				prev->next = p->next;   /* remove p from list */
				p->next = host_pairs;   /* and stick it on front */
				host_pairs = p;
			}
			break;
		}
	}
Beispiel #14
0
static void
nilwalkback(NilFlow *rcheck)
{
	Prog *p;
	ProgInfo info;
	NilFlow *r;
	
	for(r = rcheck; r != nil; r = (NilFlow*)uniqp(&r->f)) {
		p = r->f.prog;
		proginfo(&info, p);
		if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from)) {
			// Found initialization of value we're checking for nil.
			// without first finding the check, so this one is unchecked.
			return;
		}
		if(r != rcheck && p->as == ACHECKNIL && sameaddr(&p->from, &rcheck->f.prog->from)) {
			rcheck->kill = 1;
			return;
		}
	}

	// Here is a more complex version that scans backward across branches.
	// It assumes rcheck->kill = 1 has been set on entry, and its job is to find a reason
	// to keep the check (setting rcheck->kill = 0).
	// It doesn't handle copying of aggregates as well as I would like,
	// nor variables with their address taken,
	// and it's too subtle to turn on this late in Go 1.2. Perhaps for Go 1.3.
	/*
	for(r1 = r0; r1 != nil; r1 = (NilFlow*)r1->f.p1) {
		if(r1->f.active == gen)
			break;
		r1->f.active = gen;
		p = r1->f.prog;
		
		// If same check, stop this loop but still check
		// alternate predecessors up to this point.
		if(r1 != rcheck && p->as == ACHECKNIL && sameaddr(&p->from, &rcheck->f.prog->from))
			break;

		proginfo(&info, p);
		if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from)) {
			// Found initialization of value we're checking for nil.
			// without first finding the check, so this one is unchecked.
			rcheck->kill = 0;
			return;
		}
		
		if(r1->f.p1 == nil && r1->f.p2 == nil) {
			print("lost pred for %P\n", rcheck->f.prog);
			for(r1=r0; r1!=nil; r1=(NilFlow*)r1->f.p1) {
				proginfo(&info, r1->f.prog);
				print("\t%P %d %d %D %D\n", r1->f.prog, info.flags&RightWrite, sameaddr(&r1->f.prog->to, &rcheck->f.prog->from), &r1->f.prog->to, &rcheck->f.prog->from);
			}
			fatal("lost pred trail");
		}
	}

	for(r = r0; r != r1; r = (NilFlow*)r->f.p1)
		for(r2 = (NilFlow*)r->f.p2; r2 != nil; r2 = (NilFlow*)r2->f.p2link)
			nilwalkback(rcheck, r2, gen);
	*/
}
Beispiel #15
0
static void
cannot_oppo(struct connection *c
	    , struct find_oppo_bundle *b
	    , err_t ughmsg)
{
    char pcb[ADDRTOT_BUF];
    char ocb[ADDRTOT_BUF];

    addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
    addrtot(&b->our_client, 0, ocb, sizeof(ocb));

    DBG(DBG_OPPO,
	openswan_log("Can not opportunistically initiate for %s to %s: %s"
		     , ocb, pcb, ughmsg));

    whack_log(RC_OPPOFAILURE
	, "Can not opportunistically initiate for %s to %s: %s"
	, ocb, pcb, ughmsg);

    if (c != NULL && c->policy_next != NULL)
    {
	/* there is some policy that comes afterwards */
	struct spd_route *shunt_spd;
	struct connection *nc = c->policy_next;
	struct state *st;

	passert(c->kind == CK_TEMPLATE);
	passert(nc->kind == CK_PERMANENT);

	DBG(DBG_OPPO, DBG_log("OE failed for %s to %s, but %s overrides shunt"
			      , ocb, pcb, nc->name));

	/*
	 * okay, here we need add to the "next" policy, which is ought
	 * to be an instance.
	 * We will add another entry to the spd_route list for the specific
	 * situation that we have.
	 */

	shunt_spd = clone_thing(nc->spd, "shunt eroute policy");

	shunt_spd->next = nc->spd.next;
	nc->spd.next = shunt_spd;

	happy(addrtosubnet(&b->peer_client, &shunt_spd->that.client));

	if (sameaddr(&b->peer_client, &shunt_spd->that.host_addr))
	    shunt_spd->that.has_client = FALSE;

	/*
	 * override the tunnel destination with the one from the secondaried
	 * policy
	 */
	shunt_spd->that.host_addr = nc->spd.that.host_addr;

	/* now, lookup the state, and poke it up.
	 */

	st = state_with_serialno(nc->newest_ipsec_sa);

	/* XXX what to do if the IPSEC SA has died? */
	passert(st != NULL);

	/* link the new connection instance to the state's list of
	 * connections
	 */

	DBG(DBG_OPPO, DBG_log("installing state: %ld for %s to %s"
			      , nc->newest_ipsec_sa
			      , ocb, pcb));

#ifdef DEBUG
	if (DBGP(DBG_OPPO | DBG_CONTROLMORE))
	{
	    char state_buf[LOG_WIDTH];
	    char state_buf2[LOG_WIDTH];
	    const time_t n = now();

	    fmt_state(st, n, state_buf, sizeof(state_buf)
		      , state_buf2, sizeof(state_buf2));
	    DBG_log("cannot_oppo, failure SA1: %s", state_buf);
	    DBG_log("cannot_oppo, failure SA2: %s", state_buf2);
	}
#endif /* DEBUG */

	if (!route_and_eroute(c, shunt_spd, st))
	{
	    whack_log(RC_OPPOFAILURE
		      , "failed to instantiate shunt policy %s for %s to %s"
		      , c->name
		      , ocb, pcb);
	}
	return;
    }

    /*
     * NETKEY default for level param in tmpl is required, so no traffic will
     * transmitted until an SA is fully up
     */
    if (b->held && kern_interface != USE_NETKEY)
    {
	int failure_shunt = b->failure_shunt;

	/* Replace HOLD with b->failure_shunt.
	 * If no failure_shunt specified, use SPI_PASS -- THIS MAY CHANGE.
	 */
	if (failure_shunt == 0)
	{
	    DBG(DBG_OPPO, DBG_log("no explicit failure shunt for %s to %s; removing spurious hold shunt"
				  , ocb, pcb));
	}
	(void) replace_bare_shunt(&b->our_client, &b->peer_client
	    , b->policy_prio
	    , failure_shunt
	    , failure_shunt != 0
	    , b->transport_proto
	    , ughmsg);
    }
}