Example #1
0
/*
 * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet,
 * and return a pointer to SP.
 * OUT:	positive: a pointer to the entry for security policy leaf matched.
 *	NULL:	no apropreate SP found, the following value is set to error.
 *		0	: bypass
 *		EACCES	: discard packet.
 *		ENOENT	: ipsec_acquire() in progress, maybe.
 *		others	: error occured.
 */
struct secpolicy *
ipsec_getpolicybyaddr(struct mbuf *m, u_int dir, int flag, int *error)
{
	struct secpolicyindex spidx;
	struct secpolicy *sp;

	IPSEC_ASSERT(m != NULL, ("null mbuf"));
	IPSEC_ASSERT(error != NULL, ("null error"));
	IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
		("invalid direction %u", dir));

	sp = NULL;
	if (key_havesp(dir)) {
		/* Make an index to look for a policy. */
		*error = ipsec_setspidx(m, &spidx,
					(flag & IP_FORWARDING) ? 0 : 1);
		if (*error != 0) {
			DPRINTF(("%s: setpidx failed, dir %u flag %u\n",
				__func__, dir, flag));
			return (NULL);
		}
		spidx.dir = dir;

		sp = KEY_ALLOCSP(&spidx, dir);
	}
	if (sp == NULL)			/* No SP found, use system default. */
		sp = KEY_ALLOCSP_DEFAULT();
	IPSEC_ASSERT(sp != NULL, ("null SP"));
	return (sp);
}
Example #2
0
/*
 * 
 * Called from ip_output().
 * 1 = drop packet, 0 = continue processing packet,
 * -1 = packet was reinjected and stop processing packet
 */
int
ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *error)
{
	struct secpolicy *sp;

	if (!key_havesp(IPSEC_DIR_OUTBOUND))
		return 0;

	/*
	 * Check the security policy (SP) for the packet and, if
	 * required, do IPsec-related processing.  There are two
	 * cases here; the first time a packet is sent through
	 * it will be untagged and handled by ipsec4_checkpolicy.
	 * If the packet is resubmitted to ip_output (e.g. after
	 * AH, ESP, etc. processing), there will be a tag to bypass
	 * the lookup and related policy checking.
	 */
	if (m_tag_find(*m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) {
		*error = 0;
		return (0);
	}
	sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, error, inp);
	/*
	 * There are four return cases:
	 *    sp != NULL	 	    apply IPsec policy
	 *    sp == NULL, error == 0	    no IPsec handling needed
	 *    sp == NULL, error == -EINVAL  discard packet w/o error
	 *    sp == NULL, error != 0	    discard packet, report error
	 */
	if (sp != NULL) {
		/*
		 * Do delayed checksums now because we send before
		 * this is done in the normal processing path.
		 */
		if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
			in_delayed_cksum(*m);
			(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
		}
#ifdef SCTP
		if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP) {
			struct ip *ip = mtod(*m, struct ip *);

			sctp_delayed_cksum(*m, (uint32_t)(ip->ip_hl << 2));
			(*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP;
		}
#endif

		/* NB: callee frees mbuf */
		*error = ipsec4_process_packet(*m, sp->req);
		KEY_FREESP(&sp);
		if (*error == EJUSTRETURN) {
			/*
			 * We had a SP with a level of 'use' and no SA. We
			 * will just continue to process the packet without
			 * IPsec processing and return without error.
			 */
			*error = 0;
			goto done;
		}
		/*
		 * Preserve KAME behaviour: ENOENT can be returned
		 * when an SA acquire is in progress.  Don't propagate
		 * this to user-level; it confuses applications.
		 *
		 * XXX this will go away when the SADB is redone.
		 */
		if (*error == ENOENT)
			*error = 0;
		goto reinjected;
	} else {	/* sp == NULL */

		if (*error != 0) {
Example #3
0
/*
 * For OUTBOUND packet having a socket. Searching SPD for packet,
 * and return a pointer to SP.
 * OUT:	NULL:	no apropreate SP found, the following value is set to error.
 *		0	: bypass
 *		EACCES	: discard packet.
 *		ENOENT	: ipsec_acquire() in progress, maybe.
 *		others	: error occurred.
 *	others:	a pointer to SP
 *
 * NOTE: IPv6 mapped adddress concern is implemented here.
 */
static struct secpolicy *
ipsec_getpolicybysock(const struct mbuf *m, u_int dir, struct inpcb *inp,
    int *error)
{
	struct inpcbpolicy *pcbsp;
	struct secpolicy *currsp = NULL;	/* Policy on socket. */
	struct secpolicy *sp;

	IPSEC_ASSERT(m != NULL, ("null mbuf"));
	IPSEC_ASSERT(inp != NULL, ("null inpcb"));
	IPSEC_ASSERT(error != NULL, ("null error"));
	IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
		("invalid direction %u", dir));

	if (!key_havesp(dir)) {
		/* No SP found, use system default. */
		sp = KEY_ALLOCSP_DEFAULT();
		return (sp);
	}

	/* Set spidx in pcb. */
	*error = ipsec_setspidx_inpcb(m, inp);
	if (*error)
		return (NULL);

	pcbsp = inp->inp_sp;
	IPSEC_ASSERT(pcbsp != NULL, ("null pcbsp"));
	switch (dir) {
	case IPSEC_DIR_INBOUND:
		currsp = pcbsp->sp_in;
		break;
	case IPSEC_DIR_OUTBOUND:
		currsp = pcbsp->sp_out;
		break;
	}
	IPSEC_ASSERT(currsp != NULL, ("null currsp"));

	if (pcbsp->priv) {			/* When privilieged socket. */
		switch (currsp->policy) {
		case IPSEC_POLICY_BYPASS:
		case IPSEC_POLICY_IPSEC:
			key_addref(currsp);
			sp = currsp;
			break;

		case IPSEC_POLICY_ENTRUST:
			/* Look for a policy in SPD. */
			sp = KEY_ALLOCSP(&currsp->spidx, dir);
			if (sp == NULL)		/* No SP found. */
				sp = KEY_ALLOCSP_DEFAULT();
			break;

		default:
			ipseclog((LOG_ERR, "%s: Invalid policy for PCB %d\n",
				__func__, currsp->policy));
			*error = EINVAL;
			return (NULL);
		}
	} else {				/* Unpriv, SPD has policy. */
		sp = KEY_ALLOCSP(&currsp->spidx, dir);
		if (sp == NULL) {		/* No SP found. */
			switch (currsp->policy) {
			case IPSEC_POLICY_BYPASS:
				ipseclog((LOG_ERR, "%s: Illegal policy for "
					"non-priviliged defined %d\n",
					__func__, currsp->policy));
				*error = EINVAL;
				return (NULL);

			case IPSEC_POLICY_ENTRUST:
				sp = KEY_ALLOCSP_DEFAULT();
				break;

			case IPSEC_POLICY_IPSEC:
				key_addref(currsp);
				sp = currsp;
				break;

			default:
				ipseclog((LOG_ERR, "%s: Invalid policy for "
					"PCB %d\n", __func__, currsp->policy));
				*error = EINVAL;
				return (NULL);
			}
		}
	}
	IPSEC_ASSERT(sp != NULL,
		("null SP (priv %u policy %u", pcbsp->priv, currsp->policy));
	KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
		printf("DP %s (priv %u policy %u) allocate SP:%p (refcnt %u)\n",
			__func__, pcbsp->priv, currsp->policy, sp, sp->refcnt));
	return (sp);
}