示例#1
0
文件: log.c 项目: dotmark/libreswan
void extra_debugging(const struct connection *c)
{
	if (c == NULL) {
		reset_debugging();
		return;
	}

	if (c != NULL && c->extra_debugging != 0) {
		libreswan_log("extra debugging enabled for connection: %s",
			      bitnamesof(debug_bit_names, c->extra_debugging &
					 ~cur_debugging));
		set_debugging(cur_debugging | c->extra_debugging);
	}

	/*
	 * if any debugging is no, make sure that we log the connection
	 * we are processing, because it may not be clear in later debugging.
	 */
	if (cur_debugging) {
		char b1[CONN_INST_BUF];
		fmt_conn_instance(c, b1);
		DBG_log("processing connection %s%s",
			c->name, b1);
	}

}
示例#2
0
void
extra_debugging(const struct connection *c)
{
    if (c->extra_debugging != 0)
    {
	log("enabling for connection: %s"
	    , bitnamesof(debug_bit_names, c->extra_debugging & ~cur_debugging));
	cur_debugging |= c->extra_debugging;
    }
}
示例#3
0
文件: log.c 项目: odit/rv042
void
extra_debugging(const struct connection *c)
{
    if(c == NULL)
    {
	reset_debugging();
	return;
    }

    if (c!= NULL && c->extra_debugging != 0)
    {
	plog("enabling for connection: %s"
	    , bitnamesof(debug_bit_names, c->extra_debugging & ~cur_debugging));
	cur_debugging |= c->extra_debugging;
    }
}
示例#4
0
static initiator_function *pick_initiator(struct connection *c,
					  lset_t policy)
{
	if ((policy & POLICY_IKEV2_PROPOSE) &&
	    (policy & c->policy & POLICY_IKEV2_ALLOW) &&
	    !c->failed_ikev2) {
		/* we may try V2, and we haven't failed */
		return ikev2parent_outI1;
	} else if (policy & c->policy & POLICY_IKEV1_ALLOW) {
		/* we may try V1; Aggressive or Main Mode? */
		return (policy & POLICY_AGGRESSIVE) ? aggr_outI1 : main_outI1;
	} else {
		libreswan_log("Neither IKEv1 nor IKEv2 allowed: %s%s",
			c->failed_ikev2? "previous V2 failure, " : "",
			bitnamesof(sa_policy_bit_names, policy & c->policy));
		/*
		 * tried IKEv2, if allowed, and failed,
		 * and tried IKEv1, if allowed, and got nowhere.
		 */
		return NULL;
	}
}
示例#5
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);
		}
	}
}
示例#6
0
bool
in_struct(void *struct_ptr, struct_desc *sd
, pb_stream *ins, pb_stream *obj_pbs)
{
    err_t ugh = NULL;
    u_int8_t *cur = ins->cur;

    if (ins->roof - cur < (ptrdiff_t)sd->size) {
	ugh = builddiag("not enough room in input packet for %s", sd->name);
    } else {
	u_int8_t *roof = cur + sd->size;    /* may be changed by a length field */
	u_int8_t *outp = struct_ptr;
	bool immediate = FALSE;
	field_desc *fp;

	for (fp = sd->fields; ugh == NULL; fp++) {
	    size_t i = fp->size;

	    passert(ins->roof - cur >= (ptrdiff_t)i);
	    passert(cur - ins->cur <= (ptrdiff_t)(sd->size - i));
	    passert(outp - (cur - ins->cur) == struct_ptr);

#if 0
	    DBG(DBG_PARSING, DBG_log("%d %s"
		, (int) (cur - ins->cur), fp->name == NULL? "" : fp->name));
#endif
	    switch (fp->field_type) {
	    case ft_mbz:	/* must be zero */
		for (; i != 0; i--) {
		    if (*cur++ != 0) {
			ugh = builddiag("byte %d of %s must be zero, but is not"
			    , (int) (cur - ins->cur), sd->name);
			break;
		    }
		    *outp++ = '\0';	/* probably redundant */
		}
		break;

	    case ft_nat:	/* natural number (may be 0) */
	    case ft_len:	/* length of this struct and any following crud */
	    case ft_lv:		/* length/value field of attribute */
	    case ft_enum:	/* value from an enumeration */
	    case ft_loose_enum:	/* value from an enumeration with only some names known */
	    case ft_af_enum:	/* Attribute Format + value from an enumeration */
	    case ft_set:	/* bits representing set */
	    {
		u_int32_t n = 0;

		for (; i != 0; i--)
		    n = (n << BITS_PER_BYTE) | *cur++;

		switch (fp->field_type) {
		case ft_len:	/* length of this struct and any following crud */
		case ft_lv:	/* length/value field of attribute */
		{
		    u_int32_t len = fp->field_type == ft_len? n
			: immediate? sd->size : n + sd->size;

		    if (len < sd->size) {
			ugh = builddiag("%s of %s is smaller than minimum"
			    , fp->name, sd->name);
		    } else if (pbs_left(ins) < len) {
			ugh = builddiag("%s of %s is larger than can fit"
			    , fp->name, sd->name);
		    } else {
			roof = ins->cur + len;
		    }
		    break;
		}
		case ft_af_enum:	/* Attribute Format + value from an enumeration */
		    if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
			immediate = TRUE;
		    /* FALL THROUGH */
		case ft_enum:	/* value from an enumeration */
		    if (enum_name(fp->desc, n) == NULL) {
			ugh = builddiag("%s of %s has an unknown value: %lu"
			    , fp->name, sd->name, (unsigned long)n);
		    }
		    /* FALL THROUGH */
		case ft_loose_enum:	/* value from an enumeration with only some names known */
		    break;
		case ft_set:	/* bits representing set */
		    if (!testset(fp->desc, n)) {
			ugh = builddiag("bitset %s of %s has unknown member(s): %s"
			    , fp->name, sd->name, bitnamesof(fp->desc, n));
		    }
		    break;
		default:
			break;
		}
		i = fp->size;
		switch (i) {
		case 8/BITS_PER_BYTE:
		    *(u_int8_t *)outp = n;
		    break;
		case 16/BITS_PER_BYTE:
		    *(u_int16_t *)outp = n;
		    break;
		case 32/BITS_PER_BYTE:
		    *(u_int32_t *)outp = n;
		    break;
		default:
		    impossible();
		}
		outp += i;
		break;
	    }

	    case ft_raw:	/* bytes to be left in network-order */
		for (; i != 0; i--) {
		    *outp++ = *cur++;
		}
		break;

	    case ft_end:	/* end of field list */
		passert(cur == ins->cur + sd->size);
		if (obj_pbs != NULL) {
		    init_pbs(obj_pbs, ins->cur, roof - ins->cur, sd->name);
		    obj_pbs->container = ins;
		    obj_pbs->desc = sd;
		    obj_pbs->cur = cur;
		}
		ins->cur = roof;
		DBG(DBG_PARSING
		    , DBG_prefix_print_struct(ins, "parse ", struct_ptr, sd, TRUE));
		return TRUE;

	    default:
		impossible();
	    }
	}
    }

    /* some failure got us here: report it */
    loglog(RC_LOG_SERIOUS, ugh);
    return FALSE;
}
示例#7
0
/* print a host struct
 *
 * This code assumes that the network and host structure
 * members have the same alignment and size!  This requires
 * that all padding be explicit.
 */
void
DBG_print_struct(const char *label, const void *struct_ptr
, struct_desc *sd, bool len_meaningful)
{
    bool immediate = FALSE;
    const u_int8_t *inp = struct_ptr;
    field_desc *fp;

    DBG_log("%s%s:", label, sd->name);

    for (fp = sd->fields; fp->field_type != ft_end; fp++) {
	int i = fp->size;
	u_int32_t n = 0;

	switch (fp->field_type) {
	case ft_mbz:	/* must be zero */
	    inp += i;
	    break;
	case ft_nat:	/* natural number (may be 0) */
	case ft_len:	/* length of this struct and any following crud */
	case ft_lv:	/* length/value field of attribute */
	case ft_enum:	/* value from an enumeration */
	case ft_loose_enum:	/* value from an enumeration with only some names known */
	case ft_af_enum:	/* Attribute Format + value from an enumeration */
	case ft_set:	/* bits representing set */
	    switch (i) {
	    case 8/BITS_PER_BYTE:
		n = *(const u_int8_t *)inp;
		break;
	    case 16/BITS_PER_BYTE:
		n = *(const u_int16_t *)inp;
		break;
	    case 32/BITS_PER_BYTE:
		n = *(const u_int32_t *)inp;
		break;
	    default:
		impossible();
	    }
	    switch (fp->field_type) {
	    case ft_len:	/* length of this struct and any following crud */
	    case ft_lv:		/* length/value field of attribute */
		if (!immediate && !len_meaningful)
		    break;
		/* FALL THROUGH */
	    case ft_nat:	/* natural number (may be 0) */
		DBG_log("   %s: %lu", fp->name, (unsigned long)n);
		break;
	    case ft_af_enum:	/* Attribute Format + value from an enumeration */
		if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
		    immediate = TRUE;
		/* FALL THROUGH */
	    case ft_enum:	/* value from an enumeration */
	    case ft_loose_enum:	/* value from an enumeration with only some names known */
		DBG_log("   %s: %s", fp->name, enum_show(fp->desc, n));
		break;
	    case ft_set:	/* bits representing set */
		DBG_log("   %s: %s", fp->name, bitnamesof(fp->desc, n));
		break;
	    default:
		impossible();
		break;
	    }
	    inp += i;
	    break;

	case ft_raw:	/* bytes to be left in network-order */
	    {
		char m[50];	/* arbitrary limit on name width in log */

		snprintf(m, sizeof(m), "   %s:", fp->name);
		DBG_dump(m, inp, i);
		inp += i;
	    }
	    break;
	default:
	    impossible();
	    break;
	}
    }
}
示例#8
0
/* Handle a kernel request. Supposedly, there's a message in
 * the kernelsock socket.
 */
void
whack_handle(int whackctlfd)
{
    struct whack_message msg;
    struct sockaddr_un whackaddr;
    int whackaddrlen = sizeof(whackaddr);
    int whackfd = accept(whackctlfd, (struct sockaddr *)&whackaddr, &whackaddrlen);
    ssize_t n;

    if (whackfd < 0)
    {
	log_errno((e, "accept() failed in whack_handle()"));
	return;
    }
    n = read(whackfd, &msg, sizeof(msg));
    if (n == -1)
    {
	log_errno((e, "read() failed in whack_handle()"));
	close(whackfd);
	return;
    }

    whack_log_fd = whackfd;

    /* sanity check message */
    {
	err_t ugh = NULL;

	next_str = msg.string;
	str_roof = (char *)&msg + n;

	if (next_str > str_roof)
	{
	    ugh = builddiag("truncated message from whack: got %d bytes; expected %d.  Message ignored."
		, n, (int) sizeof(msg));
	}
	else if (msg.magic != WHACK_MAGIC)
	{
	    ugh = builddiag("message from whack has bad magic %d; should be %d; probably wrong version.  Message ignored"
		, msg.magic, WHACK_MAGIC);
	}
	else if (!unpack_str(&msg.name)		/* string 1 */
	|| !unpack_str(&msg.left.id)		/* string 2 */
	|| !unpack_str(&msg.left.cert)		/* string 3 */
	|| !unpack_str(&msg.left.updown)	/* string 4 */
#ifdef VIRTUAL_IP
	|| !unpack_str(&msg.left.virt)
#endif
	|| !unpack_str(&msg.right.id)		/* string 5 */
	|| !unpack_str(&msg.right.cert)		/* string 6 */	
	|| !unpack_str(&msg.right.updown)	/* string 7 */
#ifdef VIRTUAL_IP
	|| !unpack_str(&msg.right.virt)
#endif
	|| !unpack_str(&msg.keyid)		/* string 8 */
	|| !unpack_str(&msg.ike)		/* string 9 */
	|| !unpack_str(&msg.esp)		/* string 10 */	
	|| !unpack_str(&msg.dnshostname)	/* string 11 */
	|| str_roof - next_str != (ptrdiff_t)msg.keyval.len)	/* check chunk */
	{
	    ugh = "message from whack contains bad string";
	}
	else
	{
	    msg.keyval.ptr = next_str;	/* grab chunk */
	}

	if (ugh != NULL)
	{
	    loglog(RC_BADWHACKMESSAGE, "%s", ugh);
	    whack_log_fd = NULL_FD;
	    close(whackfd);
	    return;
	}
    }

    if (msg.whack_options)
    {
#ifdef DEBUG
	if (msg.name == NULL)
	{
	    /* we do a two-step so that if either old or new would
	     * cause the message to print, it will be printed.
	     */
	    cur_debugging |= msg.debugging;
	    DBG(DBG_CONTROL
		, DBG_log("base debugging = %s"
		    , bitnamesof(debug_bit_names, msg.debugging)));
	    cur_debugging = base_debugging = msg.debugging;
	}
	else if (!msg.whack_connection)
	{
	    struct connection *c = con_by_name(msg.name, TRUE);

	    if (c != NULL)
	    {
		c->extra_debugging = msg.debugging;
		DBG(DBG_CONTROL
		    , DBG_log("\"%s\" extra_debugging = %s"
			, c->name
			, bitnamesof(debug_bit_names, c->extra_debugging)));
	    }
	}
#endif
    }

    /* Deleting combined with adding a connection works as replace.
     * To make this more useful, in only this combination,
     * delete will silently ignore the lack of the connection.
     */
    if (msg.whack_delete)
    {
	struct connection *c = con_by_name(msg.name, !msg.whack_connection);

	/* note: this is a "while" because road warrior
	 * leads to multiple connections with the same name.
	 */
	for (; c != NULL; c = con_by_name(msg.name, FALSE))
	    delete_connection(c);
    }

    if (msg.whack_deletestate)
    {
	struct state *st = state_with_serialno(msg.whack_deletestateno);

	if (st == NULL)
	{
	    loglog(RC_UNKNOWN_NAME, "no state #%lu to delete"
		, msg.whack_deletestateno);
	}
	else
	{
	    delete_state(st);
	}
    }

    if (msg.whack_connection)
	add_connection(&msg);

    /* process "listen" before any operation that could require it */
    if (msg.whack_listen)
    {
	log("listening for IKE messages");
	listening = TRUE;
	find_ifaces();
	load_preshared_secrets();
    }
    if (msg.whack_unlisten)
    {
	log("no longer listening for IKE messages");
	listening = FALSE;
    }

    if (msg.whack_reread & REREAD_SECRETS)
    {
	load_preshared_secrets();
    }

   if (msg.whack_reread & REREAD_MYCERT)
    {
	load_mycert();
    }

   if (msg.whack_reread & REREAD_CACERTS)
    {
	load_cacerts();
    }

   if (msg.whack_reread & REREAD_CRLS)
    {
	load_crls();
    }

   if (msg.whack_list & LIST_PUBKEYS)
    {
	list_public_keys(msg.whack_utc);
    }

    if (msg.whack_list & LIST_CERTS)
    {
	list_certs(msg.whack_utc);
    }

    if (msg.whack_list & LIST_CACERTS)
    {
	list_cacerts(msg.whack_utc);
    }

    if (msg.whack_list & LIST_CRLS)
    {
	list_crls(msg.whack_utc);
    }

    if (msg.whack_key)
    {
	/* add a public key */
	struct id keyid;
	err_t ugh = atoid(msg.keyid, &keyid);

	if (ugh != NULL)
	{
	    loglog(RC_BADID, "bad --keyid \"%s\": %s", msg.keyid, ugh);
	}
	else
	{
	    if (!msg.whack_addkey)
		delete_public_keys(&keyid, msg.pubkey_alg);

	    if (msg.keyval.len == 0)
	    {
		struct key_add_continuation *kc
		    = alloc_thing(struct key_add_continuation
			, "key add continuation");
		int wfd = dup_any(whackfd);

		kc->whack_fd = wfd;
		ugh = start_adns_query(&keyid
		    , NULL
		    , T_KEY
		    , key_add_continue
		    , &kc->ac);

		if (ugh != NULL)
		{
		    key_add_ugh(&keyid, ugh);
		    close_any(wfd);
		}
	    }
	    else
	    {
		ugh = add_public_key(&keyid, DAL_LOCAL, msg.pubkey_alg
		    , &msg.keyval, &pubkeys);
		if (ugh != NULL)
		    loglog(RC_LOG_SERIOUS, "%s", ugh);
	    }
	}
    }