예제 #1
0
파일: pbs.c 프로젝트: 1309578252/Openswan
void pbs_poke(pb_stream *pbs, int offset, int value)
{
    if(offset < pbs_room(pbs)) {
	pbs->start[offset] = value;

	if(pbs->cur < pbs->start + offset) {
	    pbs->cur = pbs->start + offset;
	}
    } else {
	openswan_log("pbs_peek offset:%d < pbs_room(pbs):%d", offset, pbs_room(pbs));
	pexpect(offset < pbs_room(pbs));
    }
}
예제 #2
0
/* process an input packet, possibly generating a reply.
 *
 * If all goes well, this routine eventually calls a state-specific
 * transition function.
 */
void process_packet(struct msg_digest **mdp)
{
	struct msg_digest *md = *mdp;
	struct state *st = NULL;
	int vmaj, vmin;
	enum state_kind from_state = STATE_UNDEFINED;   /* state we started in */

#define SEND_NOTIFICATION(t) { \
		if (st) \
			send_notification_from_state(st, from_state, t); \
		else \
			send_notification_from_md(md, t); }

	if (!in_struct(&md->hdr, &isakmp_hdr_desc, &md->packet_pbs,
		       &md->message_pbs)) {
		/*
		 * The packet was very badly mangled. We can't be sure of any
		 * content - not even to look for major version number!
		 * So we'll just silently drop it
		 */
		libreswan_log("Received packet with mangled IKE header - dropped");
		SEND_NOTIFICATION(PAYLOAD_MALFORMED);
		return;
	}

	if (md->packet_pbs.roof < md->message_pbs.roof) {
		/* I don't think this can happen if in_struct() did not fail */
		libreswan_log(
			"received packet size (%u) is smaller than from "
			"size specified in ISAKMP HDR (%u) - packet dropped",
			(unsigned) pbs_room(&md->packet_pbs),
			md->hdr.isa_length);
		/* abort processing corrupt packet */
		return;
	} else if (md->packet_pbs.roof > md->message_pbs.roof) {
		/*
		 * Some (old?) versions of the Cisco VPN client send an additional
		 * 16 bytes of zero bytes - Complain but accept it
		 */
		DBG(DBG_CONTROL, {
			DBG_log(
			"size (%u) in received packet is larger than the size "
			"specified in ISAKMP HDR (%u) - ignoring extraneous bytes",
			(unsigned) pbs_room(&md->packet_pbs),
			md->hdr.isa_length);
			DBG_dump("extraneous bytes:", md->message_pbs.roof,
				md->packet_pbs.roof - md->message_pbs.roof);
		});
예제 #3
0
파일: demux.c 프로젝트: mkj/libreswan
/* process an input packet, possibly generating a reply.
 *
 * If all goes well, this routine eventually calls a state-specific
 * transition function.
 */
void process_packet(struct msg_digest **mdp)
{
	struct msg_digest *md = *mdp;
	int vmaj, vmin;

	if (!in_struct(&md->hdr, &isakmp_hdr_desc, &md->packet_pbs,
		       &md->message_pbs)) {
		/* The packet was very badly mangled. We can't be sure of any
		 * content - not even to look for major version number!
		 * So we'll just drop it.
		 */
		libreswan_log("Received packet with mangled IKE header - dropped");
		send_notification_from_md(md, PAYLOAD_MALFORMED);
		return;
	}

	if (md->packet_pbs.roof > md->message_pbs.roof) {
		/* Some (old?) versions of the Cisco VPN client send an additional
		 * 16 bytes of zero bytes - Complain but accept it
		 */
		DBG(DBG_CONTROL, {
			DBG_log(
			"size (%u) in received packet is larger than the size "
			"specified in ISAKMP HDR (%u) - ignoring extraneous bytes",
			(unsigned) pbs_room(&md->packet_pbs),
			md->hdr.isa_length);
			DBG_dump("extraneous bytes:", md->message_pbs.roof,
				md->packet_pbs.roof - md->message_pbs.roof);
		});
예제 #4
0
파일: pbs.c 프로젝트: 1309578252/Openswan
int pbs_peek(pb_stream *pbs, int offset)
{
    if(offset < pbs_room(pbs)) {
	return pbs->start[offset];
    } else {
	return 0;
    }
}
예제 #5
0
파일: pbs.c 프로젝트: 1309578252/Openswan
int pbs_append(pb_stream *dest, int destoffset
		, pb_stream *src, int offset, int length)
{
    /* -1 means end of destination stream */
    if(destoffset == -1) {
	destoffset = pbs_offset(dest);
    }

    if(destoffset > pbs_room(dest) ||
       destoffset + length > pbs_room(dest)) {
	return 0;
    }
    
    if(offset > pbs_room(src) ||
       offset + length > pbs_room(src)) {
	return 0;
    }

    memcpy(&dest->start[destoffset], &src->start[offset], length);

    if(dest->cur < (dest->start + destoffset + length)) {
	dest->cur = dest->start + (destoffset + length);
    }
}
예제 #6
0
/**
 * nat_traversal_natoa_lookup()
 * 
 * Look for NAT-OA in message
 */
void nat_traversal_natoa_lookup(struct msg_digest *md)
{
	struct payload_digest *p;
	struct state *st = md->st;
	int i;
	ip_address ip;

	if (!st || !md->iface) {
		loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
			__FILE__, __LINE__);
		return;
	}

	/** Count NAT-OA **/
	for (p = md->chain[ISAKMP_NEXT_NATOA_R], i=0; p != NULL; p = p->next, i++);

#if 0
	DBG_log("NAT-Traversal: received %d NAT-OA.", i);
#endif

	if (i==0) {
		return;
	}
	else if (!(st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER))) {
		loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "
			"ignored because peer is not NATed", i);
		return;
	}
	else if (i>1) {
		loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. "
			"using first, ignoring others", i);
	}

	/** Take first **/
	p = md->chain[ISAKMP_NEXT_NATOA_R];

	DBG(DBG_PARSING,
		DBG_dump("NAT-OA:", p->pbs.start, pbs_room(&p->pbs));
	);
예제 #7
0
파일: pbs.c 프로젝트: 1309578252/Openswan
int pbs_room_get(pb_stream *pbs) {
    return pbs_room(pbs);
}
예제 #8
0
void recv_pcap_packet_gen(u_char *user,
			  const struct pcap_pkthdr *h,
			  const u_char *bytes)
{
	struct msg_digest *md;
	u_int32_t *dlt;
	struct iphdr  *ip;
	struct udphdr *udp;
	u_char    *ike;
	const struct iface_port *ifp = &if1;
	int packet_len;
	err_t from_ugh;

	union {
		struct sockaddr sa;
		struct sockaddr_in sa_in4;
		struct sockaddr_in6 sa_in6;
	} from;

	md = alloc_md();
	dlt = (u_int32_t *)bytes;
	if (*dlt != PF_INET)
		return;

	ip  = (struct iphdr *)(dlt + 1);
	udp = (struct udphdr *)(dlt + ip->ihl + 1);
	ike = (u_char *)(udp + 1);

	from.sa_in4.sin_addr.s_addr = ip->saddr;
	from.sa_in4.sin_port        = udp->source;

	md->iface = ifp;
	packet_len = h->len - (ike - bytes);

	happy(anyaddr(addrtypeof(&ifp->ip_addr), &md->sender));

	from_ugh = initaddr((void *) &from.sa_in4.sin_addr,
			    sizeof(from.sa_in4.sin_addr),
			    AF_INET, &md->sender);
	setportof(from.sa_in4.sin_port, &md->sender);
	md->sender_port = ntohs(from.sa_in4.sin_port);

	cur_from      = &md->sender;
	cur_from_port = md->sender_port;

	/* Clone actual message contents
	 * and set up md->packet_pbs to describe it.
	 */
	init_pbs(&md->packet_pbs,
		 clone_bytes(ike, packet_len,
			     "message buffer in comm_handle()"),
		 packet_len, "packet");

	DBG_log("*received %d bytes from %s:%u on %s (port=%d)",
		(int) pbs_room(&md->packet_pbs),
		ip_str(&md->sender), (unsigned) md->sender_port,
		ifp->ip_dev->id_rname,
		ifp->port);

	DBG_dump("", md->packet_pbs.start, pbs_room(&md->packet_pbs));

	process_packet(&md);

	if (md != NULL)
		release_md(md);

	cur_state = NULL;
	reset_cur_connection();
	cur_from = NULL;
}
예제 #9
0
static stf_status aggr_inI1_outR1_common(struct msg_digest *md,
					 int authtype)
{
	/* With Aggressive Mode, we get an ID payload in this, the first
	 * message, so we can use it to index the preshared-secrets
	 * when the IP address would not be meaningful (i.e. Road
	 * Warrior).  So our first task is to unravel the ID payload.
	 */
	struct state *st;
	struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
	struct connection *c = find_host_connection(&md->iface->ip_addr,
						    md->iface->port,
						    &md->sender,
						    md->sender_port, LEMPTY);

#if 0
	if (c == NULL && md->iface->ike_float) {
		c = find_host_connection(&md->iface->addr,
					 pluto_nat_port,
					 &md->sender, md->sender_port, LEMPTY);
	}
#endif

	if (c == NULL) {
		/* see if a wildcarded connection can be found */
		pb_stream pre_sa_pbs = sa_pd->pbs;
		lset_t policy = preparse_isakmp_sa_body(&pre_sa_pbs) |
				POLICY_AGGRESSIVE;

		c = find_host_connection(&md->iface->ip_addr, pluto_port,
					 (ip_address*)NULL, md->sender_port,
					 policy);
		if (c == NULL || (c->policy & POLICY_AGGRESSIVE) == 0) {
			ipstr_buf b;

			loglog(RC_LOG_SERIOUS, "initial Aggressive Mode message from %s"
			       " but no (wildcard) connection has been configured%s%s",
			       ipstr(&md->sender, &b),
			       (policy != LEMPTY) ? " with policy=" : "",
			       (policy != LEMPTY) ?
			       bitnamesof(sa_policy_bit_names, policy) : "");
			/* XXX notification is in order! */
			return STF_IGNORE;
		}
		/* Create a temporary connection that is a copy of this one.
		 * His ID isn't declared yet.
		 */
		c = rw_instantiate(c, &md->sender, NULL, NULL);
	}

	/* Set up state */
	cur_state = md->st = st = new_state();  /* (caller will reset cur_state) */
	st->st_connection = c;
	st->st_remoteaddr = md->sender;
	st->st_remoteport = md->sender_port;
	st->st_localaddr  = md->iface->ip_addr;
	st->st_localport  = md->iface->port;
	st->st_interface  = md->iface;
	change_state(st, STATE_AGGR_R1);

	/* until we have clue who this is, then be conservative about allocating
	 * them any crypto bandwidth
	 */
	st->st_import = pcim_stranger_crypto;

	st->st_policy |= POLICY_AGGRESSIVE;

	st->st_oakley.auth = authtype;

	if (!ikev1_decode_peer_id(md, FALSE, TRUE)) {
		char buf[IDTOA_BUF];
		ipstr_buf b;

		(void) idtoa(&st->st_connection->spd.that.id, buf,
			     sizeof(buf));
		loglog(RC_LOG_SERIOUS,
		       "initial Aggressive Mode packet claiming to be from %s"
		       " on %s but no connection has been authorized",
		       buf, ipstr(&md->sender, &b));
		/* XXX notification is in order! */
		return STF_FAIL + INVALID_ID_INFORMATION;
	}

	c = st->st_connection;

	extra_debugging(c);
	st->st_try = 0;                                 /* Not our job to try again from start */
	st->st_policy = c->policy & ~POLICY_IPSEC_MASK; /* only as accurate as connection */

	memcpy(st->st_icookie, md->hdr.isa_icookie, COOKIE_SIZE);
	get_cookie(FALSE, st->st_rcookie, COOKIE_SIZE, &md->sender);

	insert_state(st); /* needs cookies, connection, and msgid (0) */

	st->st_doi = ISAKMP_DOI_IPSEC;
	st->st_situation = SIT_IDENTITY_ONLY; /* We only support this */

	{
		ipstr_buf b;

		libreswan_log("responding to Aggressive Mode, state #%lu, connection \"%s\" from %s",
			st->st_serialno, st->st_connection->name,
			ipstr(&c->spd.that.host_addr, &b));
	}

	merge_quirks(st, md);

	set_nat_traversal(st, md);

	/* save initiator SA for HASH */
	clonereplacechunk(st->st_p1isa, sa_pd->pbs.start,
		pbs_room(&sa_pd->pbs), "sa in aggr_inI1_outR1()");

	/*
	 * parse_isakmp_sa picks the right group, which we need to know
	 * before we do any calculations. We will call it again to have it
	 * emit the winning SA into the output.
	 */
	/* SA body in */
	{
		pb_stream sabs = sa_pd->pbs;

		RETURN_STF_FAILURE(parse_isakmp_sa_body(&sabs,
							&sa_pd->payload.sa,
							NULL, FALSE, st));
	}

	/* KE in */
	RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", st->st_oakley.group,
				     &md->chain[ISAKMP_NEXT_KE]->pbs));

	/* Ni in */
	RETURN_STF_FAILURE(accept_v1_nonce(md, &st->st_ni, "Ni"));

	{
		struct ke_continuation *ke = alloc_thing(
			struct ke_continuation,
			"outI2 KE");

		ke->ke_md = md;
		set_suspended(st, md);

		if (!st->st_sec_in_use) {
			/* need to calculate KE and Nonce */
			pcrc_init(&ke->ke_pcrc, aggr_inI1_outR1_continue1);
			return build_ke(&ke->ke_pcrc, st, st->st_oakley.group,
					st->st_import);
		} else {
			/* KE and Nonce calculated */
			ke->ke_pcrc.pcrc_serialno = st->st_serialno;	/* transitional */
			return aggr_inI1_outR1_tail(&ke->ke_pcrc, NULL);
		}
	}
}