Exemple #1
0
static void conn_default(struct starter_conn *conn,
		  struct starter_conn *def)
{
	int i;

	/* structure copy to start */
	*conn = *def;

	/* unlink it */
	conn->link.tqe_next = NULL;
	conn->link.tqe_prev = NULL;

	conn->left.iface = clone_str(def->left.iface, "conn default left iface");
	conn->left.id = clone_str(def->left.id, "conn default leftid");
	conn->left.rsakey1 = clone_thing(def->left.rsakey1, "conn default left rsakey1");
	conn->left.rsakey2 = clone_thing(def->left.rsakey2, "conn default left rsakey2");
	conn->right.iface = clone_str(def->right.iface, "conn default right iface");
	conn->right.id = clone_str(def->right.id, "conn default rightid");
	conn->right.rsakey1 = clone_thing(def->right.rsakey1, "conn default right rsakey1");
	conn->right.rsakey2 = clone_thing(def->right.rsakey2, "conn default right rsakey2");

	for (i = 0; i < KSCF_MAX; i++) {
		conn->left.strings[i] = clone_str(def->left.strings[i], "conn default left item");
		conn->right.strings[i] = clone_str(def->right.strings[i], "conn default right item");
	}
	for (i = 0; i < KNCF_MAX; i++) {
		conn->left.options[i] = def->left.options[i];
		conn->right.options[i] = def->right.options[i];
	}
	for (i = 0; i < KSF_MAX; i++)
		conn->strings[i] = clone_str(def->strings[i], "conn default string item");
	for (i = 0; i < KBF_MAX; i++)
		conn->options[i] = def->options[i];

	conn->esp = clone_str(def->esp, "conn default esp");
	conn->ike = clone_str(def->ike, "conn default ike");

	conn->modecfg_dns1 = clone_str(def->modecfg_dns1, "conn default dns1");
	conn->modecfg_dns2 = clone_str(def->modecfg_dns2, "conn default dns2");
	conn->modecfg_domain = clone_str(def->modecfg_domain, "conn default domain");
	conn->modecfg_banner = clone_str(def->modecfg_banner, "conn default banner");
#ifdef HAVE_LABELED_IPSEC
	conn->policy_label = clone_str(def->policy_label, "conn default policy_label");
#endif
	conn->policy = def->policy;
}
Exemple #2
0
/*
 * this routine takes two proposals and conjoins them (or)
 */
struct db_sa *sa_merge_proposals(struct db_sa *a, struct db_sa *b)
{
	struct db_sa *n;
	unsigned int i, j, k;

	if (a == NULL || a->prop_conj_cnt == 0)
		return sa_copy_sa(b, 0);

	if (b == NULL || b->prop_conj_cnt == 0)
		return sa_copy_sa(a, 0);

	n = clone_thing(*a, "conjoin sa");

	passert(a->prop_conj_cnt == b->prop_conj_cnt);
	passert(a->prop_conj_cnt == 1);

	n->prop_conjs =
		clone_bytes(n->prop_conjs,
			    n->prop_conj_cnt * sizeof(n->prop_conjs[0]),
			    "sa copy prop conj array");

	for (i = 0; i < n->prop_conj_cnt; i++) {
		struct db_prop_conj *pca = &n->prop_conjs[i];
		struct db_prop_conj *pcb = &b->prop_conjs[i];

		passert(pca->prop_cnt == pcb->prop_cnt);
		passert(pca->prop_cnt == 1);

		pca->props = clone_bytes(pca->props,
					 pca->prop_cnt * sizeof(pca->props[0]),
					 "sa copy prop array");

		for (j = 0; j < pca->prop_cnt; j++) {
			struct db_prop *pa = &pca->props[j];
			struct db_prop *pb = &pcb->props[j];
			struct db_trans *t;
			int t_cnt = (pa->trans_cnt + pb->trans_cnt);

			t = alloc_bytes(t_cnt * sizeof(pa->trans[0]),
					"sa copy trans array");

			memcpy(t, pa->trans, (pa->trans_cnt) *
			       sizeof(pa->trans[0]));
			memcpy(t + (pa->trans_cnt),
			       pb->trans,
			       (pb->trans_cnt) * sizeof(pa->trans[0]));

			pa->trans = t;
			pa->trans_cnt = t_cnt;
			for (k = 0; k < pa->trans_cnt; k++)
				clone_trans(&pa->trans[k], 0);
		}
	}

	n->parentSA = a->parentSA;
	return n;
}
Exemple #3
0
/* Get a state object.
 * Caller must schedule an event for this object so that it doesn't leak.
 * Caller must insert_state().
 */
struct state *
new_state(void)
{
    static const struct state blank_state;	/* initialized all to zero & NULL */
    static so_serial_t next_so = SOS_FIRST;
    struct state *st;

    st = clone_thing(blank_state, "struct state in new_state()");
    st->st_serialno = next_so++;
    passert(next_so > SOS_FIRST);	/* overflow can't happen! */
    st->st_whack_sock = NULL_FD;

    anyaddr(AF_INET, &st->hidden_variables.st_nat_oa);
    anyaddr(AF_INET, &st->hidden_variables.st_natd);

    DBG(DBG_CONTROL, DBG_log("creating state object #%lu at %p"
			     , st->st_serialno, (void *) st));
    return st;
}
Exemple #4
0
struct db_sa *sa_copy_sa(struct db_sa *sa, int extra)
{
    unsigned int i;
    struct db_sa *nsa;

    nsa = clone_thing(*sa, "sa copy prop_conj");
    nsa->dynamic = TRUE;
    nsa->parentSA= sa->parentSA;

    nsa->prop_conjs =
	clone_bytes(nsa->prop_conjs
		    , (nsa->prop_conj_cnt+extra)*sizeof(nsa->prop_conjs[0])
		    , "sa copy prop conj array");

    for(i=0; i<nsa->prop_conj_cnt; i++) {
	clone_propconj(&nsa->prop_conjs[i], 0);
    }

    return nsa;
}
Exemple #5
0
/*
 * clone the sa, but keep only the first transform (if any) of the first proposal (if any)
 * ??? does this make sense?
 */
struct db_sa *sa_copy_sa_first(struct db_sa *sa)
{
	struct db_sa *nsa;
	struct db_prop_conj *pc;
	struct db_prop *p;

	nsa = clone_thing(*sa, "sa copy prop_conj");
	nsa->dynamic = TRUE;
	if (nsa->prop_conj_cnt == 0)
		return nsa;

	nsa->prop_conj_cnt = 1;
	nsa->prop_conjs = clone_bytes(nsa->prop_conjs,
				      sizeof(nsa->prop_conjs[0]),
				      "sa copy 1 prop conj array");

	pc = &nsa->prop_conjs[0];
	if (pc->prop_cnt == 0)
		return nsa;

	pc->prop_cnt = 1;
	pc->props = clone_bytes(pc->props,
				sizeof(pc->props[0]),
				"sa copy 1 prop array");

	p = &pc->props[0];
	if (p->trans_cnt == 0)
		return nsa;

	p->trans_cnt = 1;
	p->trans = clone_bytes(p->trans,
			       sizeof(p->trans[0]),
			       "sa copy 1 trans array");

	clone_trans(&p->trans[0], 0);
	return nsa;
}
Exemple #6
0
/*
 * stores a chained list of end certs and CA certs
 *
 * @verified_ca is a copied list of the verified authcerts that have
 * been placed in the global authcert chain
 */
void store_x509certs(x509cert_t **firstcert, x509cert_t **verified_ca,
					     bool strict)
{
	x509cert_t *cacerts = NULL;
	x509cert_t **pp = firstcert;

	/* first extract CA certs, discarding root CA certs */

	while (*pp != NULL) {
		x509cert_t *cert = *pp;

		if (cert->isCA) {
			*pp = cert->next;

			/* we don't accept self-signed CA certs */
			if (same_dn(cert->issuer, cert->subject)) {
				libreswan_log("self-signed cacert rejected");
				free_x509cert(cert);
			} else {
				/* insertion into temporary chain of candidate CA certs */
				cert->next = cacerts;
				cacerts = cert;
			}
		} else {
			pp = &cert->next;
		}
	}

	/* now verify the candidate CA certs */
	x509cert_t *ver = NULL;

	while (cacerts != NULL) {
		realtime_t valid_until;
		x509cert_t *cert = cacerts;

		cacerts = cacerts->next;

		if (trust_authcert_candidate(cert, cacerts) &&
		    verify_x509cert(cert, strict, &valid_until, cacerts)) {
			add_authcert(cert, AUTH_CA);
			if (ver == NULL) {
				ver = clone_thing(*cert, "x509cert_t");
				*verified_ca = ver;
			} else {
				ver->next = clone_thing(*cert, "x509cert_t");
				ver = ver->next;
			}
			ver->next = NULL;
		} else {
			libreswan_log("intermediate cacert rejected");
			free_x509cert(cert);
		}
	}

	/* now verify the end certificates */

	pp = firstcert;

	while (*pp != NULL) {
		realtime_t valid_until;
		x509cert_t *cert = *pp;

		if (verify_x509cert(cert, strict, &valid_until, NULL)) {
			DBG(DBG_X509 | DBG_PARSING,
			    DBG_log("public key validated"));
			add_x509_public_key(NULL, cert, valid_until,
					    DAL_SIGNED);
		} else {
			libreswan_log("X.509 certificate rejected");
		}
		*pp = cert->next;
		free_x509cert(cert);
	}
}
Exemple #7
0
struct private_key_stuff *lsw_nss_foreach_private_key_stuff(secret_eval func,
							    void *uservoid,
							    lsw_nss_buf_t err)
{
	/*
	 * So test for error with "if (err[0]) ..." works.
	 */
	err[0] = '\0';

	PK11SlotInfo *slot = lsw_nss_get_authenticated_slot(err);
	if (slot == NULL) {
		return NULL;
	}

	SECKEYPrivateKeyList *list = PK11_ListPrivateKeysInSlot(slot);
	if (list == NULL) {
		snprintf(err, sizeof(lsw_nss_buf_t), "no list");
		PK11_FreeSlot(slot);
		return NULL;
	}

	int line = 1;

	struct private_key_stuff *result = NULL;

	SECKEYPrivateKeyListNode *node;
	for (node = PRIVKEY_LIST_HEAD(list);
             !PRIVKEY_LIST_END(node, list);
	     node = PRIVKEY_LIST_NEXT(node)) {

		if (SECKEY_GetPrivateKeyType(node->key) != rsaKey) {
			/* only rsa for now */
			continue;
		}

		struct private_key_stuff pks = {
			.kind = PPK_RSA,
			.on_heap = TRUE,
		};

		{
			SECItem *nss_ckaid
				= PK11_GetLowLevelKeyIDForPrivateKey(node->key);
			if (nss_ckaid == NULL) {
				// fprintf(stderr, "ckaid not found\n");
				continue;
			}
			const char *err = form_ckaid_nss(nss_ckaid,
							 &pks.u.RSA_private_key.pub.ckaid);
			SECITEM_FreeItem(nss_ckaid, PR_TRUE);
			if (err) {
				// fprintf(stderr, "ckaid not found\n");
				continue;
			}
		}

		{
			SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(node->key);
			if (pubkey != NULL) {
				fill_RSA_public_key(&pks.u.RSA_private_key.pub, pubkey);
				SECKEY_DestroyPublicKey(pubkey);
			}
		}

		/*
		 * Only count private keys that get processed.
		 */
		pks.line = line++;

		int ret = func(NULL, &pks, uservoid);
		if (ret == 0) {
			/*
			 * save/return the result.
			 *
			 * XXX: Potential Memory leak.
			 *
			 * lsw_foreach_secret() + lsw_get_pks()
			 * returns an object that must not be freed
			 * BUT lsw_nss_foreach_private_key_stuff()
			 * returns an object that must be freed.
			 *
			 * For moment ignore this - as only caller is
			 * showhostkey.c which quickly exits.
			 */
			result = clone_thing(pks, "pks");
			break;
		}

		freeanyckaid(&pks.u.RSA_private_key.pub.ckaid);
		freeanychunk(pks.u.RSA_private_key.pub.e);
		freeanychunk(pks.u.RSA_private_key.pub.n);

		if (ret < 0) {
			break;
		}
	}

	SECKEY_DestroyPrivateKeyList(list);
	PK11_FreeSlot(slot);

	return result;
}
Exemple #8
0
struct raw_iface *
find_raw_ifaces6(void)
{

    /* Get list of interfaces with IPv6 addresses from system from /proc/net/if_inet6).
     *
     * Documentation of format?
     * RTFS: linux-2.2.16/net/ipv6/addrconf.c:iface_proc_info()
     *       linux-2.4.9-13/net/ipv6/addrconf.c:iface_proc_info()
     *
     * Sample from Gerhard's laptop:
     *	00000000000000000000000000000001 01 80 10 80       lo
     *	30490009000000000000000000010002 02 40 00 80   ipsec0
     *	30490009000000000000000000010002 07 40 00 80     eth0
     *	fe80000000000000025004fffefd5484 02 0a 20 80   ipsec0
     *	fe80000000000000025004fffefd5484 07 0a 20 80     eth0
     *
     * Each line contains:
     * - IPv6 address: 16 bytes, in hex, no punctuation
     * - ifindex: 1 byte, in hex
     * - prefix_len: 1 byte, in hex
     * - scope (e.g. global, link local): 1 byte, in hex
     * - flags: 1 byte, in hex
     * - device name: string, followed by '\n'
     */
    struct raw_iface *rifaces = NULL;
    static const char proc_name[] = "/proc/net/if_inet6";
    FILE *proc_sock = fopen(proc_name, "r");

    if (proc_sock == NULL)
    {
	DBG(DBG_CONTROL, DBG_log("could not open %s", proc_name));
    }
    else
    {
	for (;;)
	{
	    struct raw_iface ri;
	    unsigned short xb[8];	/* IPv6 address as 8 16-bit chunks */
	    char sb[8*5];	/* IPv6 address as string-with-colons */
	    unsigned int if_idx;	/* proc field, not used */
	    unsigned int plen;	/* proc field, not used */
	    unsigned int scope;	/* proc field, used to exclude link-local */
	    unsigned int dad_status;	/* proc field, not used */
	    /* ??? I hate and distrust scanf -- DHR */
	    int r = fscanf(proc_sock
		, "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx"
		  " %02x %02x %02x %02x %20s\n"
		, xb+0, xb+1, xb+2, xb+3, xb+4, xb+5, xb+6, xb+7
		, &if_idx, &plen, &scope, &dad_status, ri.name);

	    /* ??? we should diagnose any problems */
	    if (r != 13)
		break;

	    /* ignore addresses with link local scope.
	     * From linux-2.4.9-13/include/net/ipv6.h:
	     * IPV6_ADDR_LINKLOCAL	0x0020U
	     * IPV6_ADDR_SCOPE_MASK	0x00f0U
	     */
	    if ((scope & 0x00f0U) == 0x0020U)
		continue;

	    snprintf(sb, sizeof(sb)
		, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
		, xb[0], xb[1], xb[2], xb[3], xb[4], xb[5], xb[6], xb[7]);

	    happy(ttoaddr(sb, 0, AF_INET6, &ri.addr));

	    if (!isunspecaddr(&ri.addr))
	    {
		DBG(DBG_CONTROL
		    , DBG_log("found %s with address %s"
			, ri.name, sb));
		ri.next = rifaces;
		rifaces = clone_thing(ri, "struct raw_iface");
	    }
	}
	fclose(proc_sock);
    }

    return rifaces;
}
Exemple #9
0
struct raw_iface *
find_raw_ifaces4(void)
{
    static const int on = TRUE;	/* by-reference parameter; constant, we hope */
    int j;	/* index into buf */
    static int    num=64;    /* number of interfaces */
    struct ifconf ifconf;
    struct ifreq *buf;	     /* for list of interfaces -- arbitrary limit */
    struct raw_iface *rifaces = NULL;
    int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);    /* Get a UDP socket */

    /* get list of interfaces with assigned IPv4 addresses from system */

    if (master_sock == -1)
	exit_log_errno((e, "socket() failed in find_raw_ifaces4()"));

    if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR
		   , (const void *)&on, sizeof(on)) < 0)
	    exit_log_errno((e, "setsockopt() in find_raw_ifaces4()"));

    /* bind the socket */
    {
	ip_address any;

	happy(anyaddr(AF_INET, &any));
	setportof(htons(pluto_port), &any);
	if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0)
	    exit_log_errno((e, "bind() failed in find_raw_ifaces4()"));
    }

    buf = NULL;
   
    /* a million interfaces is probably the maximum, ever... */
    while(num < (1024*1024)) {
	    /* Get local interfaces.  See netdevice(7). */
	    ifconf.ifc_len = num * sizeof(struct ifreq);
	    buf = (void *) realloc(buf, ifconf.ifc_len);
	    if (!buf)
		    exit_log_errno((e, "realloc of %d in find_raw_ifaces4()",
				    ifconf.ifc_len));
	    memset(buf, 0, num*sizeof(struct ifreq));
	    ifconf.ifc_buf = (void *) buf;
	    
	    if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
		    exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));
	    
	    /* if we got back less than we asked for, we have them all */
	    if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num))
		    break;
	    
	    /* try again and ask for more this time */
	    num *= 2;
    }
  
    /* Add an entry to rifaces for each interesting interface. */
    for (j = 0; (j+1) * sizeof(struct ifreq) <= (size_t)ifconf.ifc_len; j++)
    {
	struct raw_iface ri;
	const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr;
	struct ifreq auxinfo;

	/* ignore all but AF_INET interfaces */
	if (rs->sin_family != AF_INET)
	    continue;	/* not interesting */

	/* build a NUL-terminated copy of the rname field */
	memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ);
	ri.name[IFNAMSIZ] = '\0';

	/* ignore if our interface names were specified, and this isn't one */
	if (pluto_ifn_roof != 0)
	{
	    int i;

	    for (i = 0; i != pluto_ifn_roof; i++)
		if (streq(ri.name, pluto_ifn[i]))
		    break;
	    if (i == pluto_ifn_roof)
		continue;	/* not found -- skip */
	}

	/* Find out stuff about this interface.  See netdevice(7). */
	zero(&auxinfo);	/* paranoia */
	memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ);
	if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1)
	    exit_log_errno((e
		, "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()"
		, ri.name));
	if (!(auxinfo.ifr_flags & IFF_UP))
	   {
		DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is not up"
	    , ri.name));
	    continue;	/* ignore an interface that isn't UP */
	   }
        if (auxinfo.ifr_flags & IFF_SLAVE)
	   {
		DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is a slave interface"
	    , ri.name));
            continue;   /* ignore slave interfaces; they share IPs with their master */
	   }

	/* ignore unconfigured interfaces */
	if (rs->sin_addr.s_addr == 0)
	   {
		DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is unconfigured"
	    , ri.name));
	    continue;
	   }

	happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr)
	    , AF_INET, &ri.addr));

	DBG(DBG_CONTROL, DBG_log("found %s with address %s"
	    , ri.name, ip_str(&ri.addr)));
	ri.next = rifaces;
	rifaces = clone_thing(ri, "struct raw_iface");
    }

    close(master_sock);

    return rifaces;
}
struct raw_iface *find_raw_ifaces4(void)
{
	static const int on = TRUE;	/* by-reference parameter; constant, we hope */
	int j;	/* index into buf */
	struct ifconf ifconf;
	struct ifreq *buf = NULL;	/* for list of interfaces -- arbitrary limit */
	struct ifreq *bp;	/* cursor into buf */
	struct raw_iface *rifaces = NULL;
	int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);        /* Get a UDP socket */

	/*
	 * Current upper bound on number of interfaces.
	 * Tricky: because this is a static, we won't have to start from
	 * 64 in subsequent calls.
	 */
	static int num = 64;	/* number of interfaces */

	/* get list of interfaces with assigned IPv4 addresses from system */

	if (master_sock == -1)
		exit_log_errno((e, "socket() failed in find_raw_ifaces4()"));

	if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR,
		       (const void *)&on, sizeof(on)) < 0)
		exit_log_errno((e, "setsockopt() in find_raw_ifaces4()"));

	/* bind the socket */
	{
		ip_address any;

		happy(anyaddr(AF_INET, &any));
		setportof(htons(pluto_port), &any);
		if (bind(master_sock, sockaddrof(&any),
			 sockaddrlenof(&any)) < 0)
			exit_log_errno((e,
					"bind() failed in find_raw_ifaces4()"));
	}

	/* a million interfaces is probably the maximum, ever... */
	for (; num < (1024 * 1024); num *= 2) {
		/* Get num local interfaces.  See netdevice(7). */
		ifconf.ifc_len = num * sizeof(struct ifreq);
		buf = realloc(buf, ifconf.ifc_len);
		if (buf == NULL) {
			exit_log_errno((e,
					"realloc of %d in find_raw_ifaces4()",
					ifconf.ifc_len));
		}
		memset(buf, 0xDF, ifconf.ifc_len);	/* stomp */
		ifconf.ifc_buf = (void *) buf;

		if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
			exit_log_errno((e,
					"ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));


		/* if we got back less than we asked for, we have them all */
		if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num))
			break;
	}

	/* Add an entry to rifaces for each interesting interface.
	   On Apple, the size of struct ifreq depends on the contents of
	   the union. See if.h */
	for (bp = buf, j = 0;
	     bp < (unsigned char *)buf + (size_t)ifconf.ifc_len;
	     bp = (struct ifreq *)
		((unsigned char *)bp +_SIZEOF_ADDR_IFREQ(*bp)),
	     j++) {
		struct raw_iface ri;
		const struct sockaddr_in *rs =
			(struct sockaddr_in *) &bp->ifr_addr;
		struct ifreq auxinfo;

		/* ignore all but AF_INET interfaces */
		if (rs->sin_family != AF_INET)
			continue; /* not interesting */

		/* build a NUL-terminated copy of the rname field */
		memcpy(ri.name, bp->ifr_name, IFNAMSIZ);
		ri.name[IFNAMSIZ] = '\0';

		/* ignore if our interface names were specified, and this isn't one */
		if (pluto_ifn_roof != 0) {
			int i;

			for (i = 0; i != pluto_ifn_roof; i++)
				if (streq(ri.name, pluto_ifn[i]))
					break;
			if (i == pluto_ifn_roof)
				continue; /* not found -- skip */
		}

		/* Find out stuff about this interface.  See netdevice(7). */
		zero(&auxinfo); /* paranoia */
		memcpy(auxinfo.ifr_name, bp->ifr_name, IFNAMSIZ);
		if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) {
			exit_log_errno((e,
					"ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()",
					ri.name));
		}
		if (!(auxinfo.ifr_flags & IFF_UP))
			continue; /* ignore an interface that isn't UP */

		/* ignore unconfigured interfaces */
		if (rs->sin_addr.s_addr == 0)
			continue;

		happy(initaddr((const void *)&rs->sin_addr,
			       sizeof(struct in_addr),
			       AF_INET, &ri.addr));

		DBG(DBG_CONTROL, {
			ipstr_buf b;
			DBG_log("found %s with address %s",
				ri.name, ipstr(&ri.addr, &b));
		});
		ri.next = rifaces;
		rifaces = clone_thing(ri, "struct raw_iface");
	}
Exemple #11
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);
    }
}