Пример #1
0
/*
 * Check the vendor ID payload -- return the vendor ID index
 * if we find a recognized one, or UNKNOWN if we don't.
 *
 * gen ... points to Vendor ID payload.
 */
int
check_vendorid(struct isakmp_gen *gen)
{
	vchar_t vid, *vidhash;
	int i, vidlen;
	struct vendor_id *current;

	if (gen == NULL)
		return (VENDORID_UNKNOWN);

	vidlen = ntohs(gen->len) - sizeof(*gen);

	current = lookup_vendor_id_by_hash((char *)(gen + 1));
	if (!current)
		goto unknown;
	
	if (current->hash->l < vidlen)
		plog(LLV_INFO, LOCATION, NULL,
		     "received broken Microsoft ID: %s\n",
		     current->string);
	else
		plog(LLV_INFO, LOCATION, NULL,
		     "received Vendor ID: %s\n",
		     current->string);

	return current->id;

unknown:
	plog(LLV_DEBUG, LOCATION, NULL, "received unknown Vendor ID\n");
	plogdump(LLV_DEBUG, (char *)(gen + 1), vidlen);
	return (VENDORID_UNKNOWN);
}
Пример #2
0
/*
 * generate octet string for auth calculation input
 */
static rc_vchar_t *
ikev2_auth_input(struct ikev2_sa *sa, int i_to_r)
{
	rc_vchar_t *message;
	rc_vchar_t *octets = 0;
	rc_vchar_t *nonce;
	rc_vchar_t *sk;
	rc_vchar_t *id;
	struct keyed_hash *prf = sa->prf;
	uint8_t *p;
	rc_vchar_t *prf_output = 0;

	TRACE((PLOGLOC, "ikev2_auth_input(%p, %d)\n", sa, i_to_r));

	/* (draft-17)
	 * For the responder, the octets to
	 * be signed start with the first octet of the first SPI in the header
	 * of the second message and end with the last octet of the last payload
	 * in the second message.  Appended to this (for purposes of computing
	 * the signature) are the initiator's nonce Ni (just the value, not the
	 * payload containing it), and the value prf(SK_pr,IDr') where IDr' is
	 * the responder's ID payload excluding the fixed header.
	 */
	/* sign(packet | Ni | prf(SK_pr, IDr')) */

	/*
	 * the initiator signs the first message, starting with the
	 * first octet of the first SPI in the header and ending with the last
	 * octet of the last payload.  Appended to this (for purposes of
	 * computing the signature) are the responder's nonce Nr, and the value
	 * prf(SK_pi,IDi'). In the above calculation, IDi' and IDr' are the
	 * entire ID payloads excluding the fixed header.
	 */
	/* sign(packet | Nr | prf(SK_pi, IDi')) */

	/*
	 * Optionally, messages 3 and 4 MAY include a certificate, or
	 * certificate chain providing evidence that the key used to compute a
	 * digital signature belongs to the name in the ID payload. The
	 * signature or MAC will be computed using algorithms dictated by the
	 * type of key used by the signer, and specified by the Auth Method
	 * field in the Authentication payload.
	 */

	/*
	 * In the case of a pre-shared key, the AUTH
	 * value is computed as:
	 * 
	 * AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>)
	 */

#ifdef notyet
	/*
	 * For EAP methods that create a shared key as a side effect of
	 * authentication, that shared key MUST be used by both the initiator
	 * and responder to generate AUTH payloads in messages 5 and 6 using the
	 * syntax for shared secrets specified in section 2.15. The shared key
	 * from EAP is the field from the EAP specification named MSK. The
	 * shared key generated during an IKE exchange MUST NOT be used for any
	 * other purpose.
	 * 
	 * EAP methods that do not establish a shared key SHOULD NOT be used, as
	 * they are subject to a number of man-in-the-middle attacks [EAPMITM]
	 * if these EAP methods are used in other protocols that do not use a
	 * server-authenticated tunnel.  Please see the Security Considerations
	 * section for more details. If EAP methods that do not generate a
	 * shared key are used, the AUTH payloads in messages 7 and 8 MUST be
	 * generated using SK_pi and SK_pr respectively.
	 */
#endif

	/* (draft-eronen-ipsec-ikev2-clarifications-05.txt)
	 * 3.1  Data included in AUTH payload calculation
	 * 
	 * Section 2.15 describes how the AUTH payloads are calculated; this
	 * calculation involves values prf(SK_pi,IDi') and prf(SK_pr,IDr').  The
	 * text describes the method in words, but does not give clear
	 * definitions of what is signed or MACed.
	 * 
	 * The initiator's signed octets can be described as:
	 * 
	 * InitiatorSignedOctets = RealMessage1 | NonceRData | MACedIDForI
	 * GenIKEHDR = [ four octets 0 if using port 4500 ] | RealIKEHDR
	 * RealIKEHDR =  SPIi | SPIr |  . . . | Length
	 * RealMessage1 = RealIKEHDR | RestOfMessage1
	 * NonceRPayload = PayloadHeader | NonceRData
	 * InitiatorIDPayload = PayloadHeader | RestOfIDPayload
	 * RestOfInitIDPayload = IDType | RESERVED | InitIDData
	 * MACedIDForI = prf(SK_pi, RestOfInitIDPayload)
	 * 
	 * The responder's signed octets can be described as:
	 * 
	 * ResponderSignedOctets = RealMessage2 | NonceIData | MACedIDForR
	 * GenIKEHDR = [ four octets 0 if using port 4500 ] | RealIKEHDR
	 * RealIKEHDR =  SPIi | SPIr |  . . . | Length
	 * RealMessage2 = RealIKEHDR | RestOfMessage2
	 * NonceIPayload = PayloadHeader | NonceIData
	 * ResponderIDPayload = PayloadHeader | RestOfIDPayload
	 * RestOfRespIDPayload = IDType | RESERVED | InitIDData
	 * MACedIDForR = prf(SK_pr, RestOfRespIDPayload)
	 */

	if (sa->is_initiator ? i_to_r : (!i_to_r)) {
		assert(sa->my_first_message);
		message = sa->my_first_message;
	} else {
		assert(sa->peer_first_message);
		message = sa->peer_first_message;
	}
	if (i_to_r) {
		nonce = sa->n_r;
		sk = sa->sk_p_i;
		id = sa->id_i;
	} else {
		nonce = sa->n_i;
		sk = sa->sk_p_r;
		id = sa->id_r;
	}

	IF_TRACE({
		TRACE((PLOGLOC, "SK\n"));
		plogdump(PLOG_DEBUG, PLOGLOC, 0, sk->v, sk->l);
		TRACE((PLOGLOC, "ID\n"));
		plogdump(PLOG_DEBUG, PLOGLOC, 0, id->v, id->l);
	});
Пример #3
0
/* send packet, with fixing src/dst address pair. */
int
sendfromto(int s, const void *buf, size_t buflen, 
	   struct sockaddr *src, struct sockaddr *dst, int cnt)
{
	struct sockaddr_storage ss;
	socklen_t sslen;
	int len = 0, i;
	extern struct rcf_interface *rcf_interface_head;

	if (cnt <= 0) {
		TRACE((PLOGLOC, "cnt: %d\n", cnt));
		return 0;
	}

	if (src->sa_family != dst->sa_family) {
		plog(PLOG_INTERR, PLOGLOC, NULL, "address family mismatch\n");
		return -1;
	}

	memset(&ss, 0, sizeof(ss));
	sslen = sizeof(ss);
	if (getsockname(s, (struct sockaddr *)&ss, &sslen) < 0) {
		plog(PLOG_INTERR, PLOGLOC, NULL,
		     "getsockname (%s)\n", strerror(errno));
		return -1;
	}

	plog(PLOG_DEBUG, PLOGLOC, NULL,
	     "sockname %s\n", rcs_sa2str((struct sockaddr *)&ss));
	plog(PLOG_DEBUG, PLOGLOC, NULL,
	     "send packet from %s\n", rcs_sa2str(src));
	plog(PLOG_DEBUG, PLOGLOC, NULL, "send packet to %s\n", rcs_sa2str(dst));

	if (src->sa_family != SOCKADDR_FAMILY(&ss)) {
		plog(PLOG_INTERR, PLOGLOC, NULL, "address family mismatch\n");
		return -1;
	}

	switch (src->sa_family) {
#if defined(INET6) && defined(ADVAPI) && !defined(IPV6_INRIA_VERSION)
	case AF_INET6:
		{
			struct msghdr m;
			struct cmsghdr *cm;
			struct iovec iov[2];
			unsigned char cmsgbuf[256];
			struct in6_pktinfo *pi;
			int ifindex;
			struct sockaddr_in6 src6, dst6;

			memcpy(&src6, src, sizeof(src6));
			memcpy(&dst6, dst, sizeof(dst6));

			/* XXX take care of other cases, such as site-local */
			ifindex = 0;
			if (IN6_IS_ADDR_LINKLOCAL(&src6.sin6_addr)
			    || IN6_IS_ADDR_MULTICAST(&src6.sin6_addr)) {
				ifindex = src6.sin6_scope_id;	/*??? */
			}

			/* XXX some sanity check on dst6.sin6_scope_id */

			/* flowinfo for IKE?  mmm, maybe useful but for now make it 0 */
			src6.sin6_flowinfo = dst6.sin6_flowinfo = 0;

			memset(&m, 0, sizeof(m));
			m.msg_name = (caddr_t)&dst6;
			m.msg_namelen = sizeof(dst6);
			iov[0].iov_base = (char *)buf;
			iov[0].iov_len = buflen;
			m.msg_iov = iov;
			m.msg_iovlen = 1;

			memset(cmsgbuf, 0, sizeof(cmsgbuf));
			cm = (struct cmsghdr *)cmsgbuf;
			m.msg_control = (caddr_t)cm;
			m.msg_controllen =
				CMSG_SPACE(sizeof(struct in6_pktinfo));

			cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
			cm->cmsg_level = IPPROTO_IPV6;
			cm->cmsg_type = IPV6_PKTINFO;
			pi = (struct in6_pktinfo *)CMSG_DATA(cm);
			memcpy(&pi->ipi6_addr, &src6.sin6_addr,
			       sizeof(src6.sin6_addr));
			pi->ipi6_ifindex = ifindex;

			plog(PLOG_DEBUG, PLOGLOC, NULL,
			     "src6 %s %d\n",
			     rcs_sa2str((struct sockaddr *)&src6),
			     src6.sin6_scope_id);
			plog(PLOG_DEBUG, PLOGLOC, NULL,
			     "dst6 %s %d\n",
			     rcs_sa2str((struct sockaddr *)&dst6),
			     dst6.sin6_scope_id);

			for (i = 0; i < cnt; i++) {
				len = sendmsg(s, &m, 0 /*MSG_DONTROUTE */ );
				if (len < 0) {
					plog(PLOG_INTERR, PLOGLOC, NULL,
					     "sendmsg (%s)\n", strerror(errno));
					return -1;
				}
				plog(PLOG_DEBUG, PLOGLOC, NULL,
				     "%d times of %d bytes message will be sent "
				     "to %s\n", i + 1, len, rcs_sa2str(dst));
			}
			plogdump(PLOG_DEBUG, PLOGLOC, 0, (char *)buf, buflen);

			return len;
		}
#endif
	default:
		{
			int needclose = 0;
			int sendsock;

			if (rcs_cmpsa((struct sockaddr *)&ss, src) == 0) {
				sendsock = s;
				needclose = 0;
			} else {
				int yes = 1;
				/*
				 * Use newly opened socket for sending packets.
				 * NOTE: this is unsafe, because if the peer is quick enough
				 * the packet from the peer may be queued into sendsock.
				 * Better approach is to prepare bind'ed udp sockets for
				 * each of the interface addresses.
				 */
				sendsock =
					socket(src->sa_family, SOCK_DGRAM, 0);
				if (sendsock < 0) {
					plog(PLOG_INTERR, PLOGLOC, NULL,
					     "socket (%s)\n", strerror(errno));
					return -1;
				}
#ifdef SO_REUSEPORT
				if (setsockopt(sendsock, SOL_SOCKET, SO_REUSEPORT,
				     (void *)&yes, sizeof(yes)) < 0) {
					plog(PLOG_INTERR, PLOGLOC, NULL,
					     "setsockopt (%s)\n",
					     strerror(errno));
					close(sendsock);
					return -1;
				}
#else
#ifdef SO_REUSEADDR
				if (setsockopt(sendsock, SOL_SOCKET, SO_REUSEADDR,
				     (void *)&yes, sizeof(yes)) < 0) {
					plog(PLOG_INTERR, PLOGLOC, NULL,
					     "setsockopt (%s)\n",
					     strerror(errno));
					close(sendsock);
					return -1;
				}
#else
#error
#endif
#endif

#ifdef IPV6_USE_MIN_MTU
				if (src->sa_family == AF_INET6 &&
				    setsockopt(sendsock, IPPROTO_IPV6,
					       IPV6_USE_MIN_MTU, (void *)&yes,
					       sizeof(yes)) < 0) {
					plog(PLOG_INTERR, PLOGLOC, NULL,
					     "setsockopt (%s)\n",
					     strerror(errno));
					close(sendsock);
					return -1;
				}
#endif
				if (rcf_interface_head->application_bypass
				    != RCT_BOOL_OFF &&
				    setsockopt_bypass(sendsock, src->sa_family)
				    < 0) {
					close(sendsock);
					return -1;
				}

				if (bind
				    (sendsock, (struct sockaddr *)src,
				     SOCKADDR_LEN(src)) < 0) {
					plog(PLOG_INTERR, PLOGLOC, NULL,
					     "bind 1 (%s)\n", strerror(errno));
					close(sendsock);
					return -1;
				}
				needclose = 1;
			}

			for (i = 0; i < cnt; i++) {
#ifdef DEBUG
				extern uint32_t debug_send;
				static int send_count = 0;

				if (debug_send & (1 << (send_count++ % 32))) {
					/* simulate a network packet drop */
					TRACE((PLOGLOC, "debug_send %d drop\n", send_count));
					len = buflen;
				} else
#endif
					len = sendto(sendsock, buf, buflen, 0,
						     dst, SOCKADDR_LEN(dst));
				if (len < 0) {
					plog(PLOG_INTERR, PLOGLOC, NULL,
					     "sendto (%s)\n", strerror(errno));
					if (needclose)
						close(sendsock);
					return len;
				}
				plog(PLOG_DEBUG, PLOGLOC, NULL,
				     "%d times of %d bytes message will be sent "
				     "to %s\n", i + 1, len, rcs_sa2str(dst));
			}
			plogdump(PLOG_DEBUG, PLOGLOC, 0, (char *)buf, buflen);

			if (needclose)
				close(sendsock);

			return len;
		}
	}
}