Beispiel #1
0
/* accept_KE
 *
 * Check and accept DH public value (Gi or Gr) from peer's message.
 * According to RFC2409 "The Internet key exchange (IKE)" 5:
 *  The Diffie-Hellman public value passed in a KE payload, in either
 *  a phase 1 or phase 2 exchange, MUST be the length of the negotiated
 *  Diffie-Hellman group enforced, if necessary, by pre-pending the
 *  value with zeros.
 */
notification_t accept_KE(chunk_t *dest, const char *val_name,
			 const struct oakley_group_desc *gr,
			 pb_stream *pbs)
{
	if (pbs_left(pbs) != gr->bytes) {
		loglog(RC_LOG_SERIOUS,
		       "KE has %u byte DH public value; %u required",
		       (unsigned) pbs_left(pbs), (unsigned) gr->bytes);
		/* XXX Could send notification back */
		return INVALID_KEY_INFORMATION;
	}
	clonereplacechunk(*dest, pbs->cur, pbs_left(pbs), val_name);
	DBG_cond_dump_chunk(DBG_CRYPT, "DH public value received:\n", *dest);
	return NOTHING_WRONG;
}
Beispiel #2
0
notification_t
accept_nonce(struct msg_digest *md, chunk_t *dest
	     , const char *name, enum next_payload_types paynum)
{
    pb_stream *nonce_pbs = &md->chain[paynum]->pbs;
    size_t len = pbs_left(nonce_pbs);

    if (len < MINIMUM_NONCE_SIZE || MAXIMUM_NONCE_SIZE < len)
    {
	loglog(RC_LOG_SERIOUS, "%s length not between %d and %d"
	    , name , MINIMUM_NONCE_SIZE, MAXIMUM_NONCE_SIZE);
	return PAYLOAD_MALFORMED;	/* ??? */
    }
    clonereplacechunk(*dest, nonce_pbs->cur, len, "nonce");
    return NOTHING_WRONG;
}
Beispiel #3
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);
		}
	}
}