Пример #1
0
/*
 * This function is used to validate the returned proposal (protection suite)
 * we get from the responder against a proposal we sent. Only run as initiator.
 * We return 0 if a match is found (in any transform of this proposal), 1
 * otherwise. Also see note in sa_add_transform() below.
 */
static int
sa_validate_proto_xf(struct proto *match, struct payload *xf, int phase)
{
	struct attr_validation_state *avs;
	struct proto_attr *pa;
	int             found = 0;
	size_t          i;
	u_int8_t        xf_id;

	if (!match->xf_cnt)
		return 0;

	if (match->proto != GET_ISAKMP_PROP_PROTO(xf->context->p)) {
		LOG_DBG((LOG_SA, 70, "sa_validate_proto_xf: proto %p (#%d) "
		    "protocol mismatch", match, match->no));
		return 1;
	}
	avs = (struct attr_validation_state *)calloc(1, sizeof *avs);
	if (!avs) {
		log_error("sa_validate_proto_xf: calloc (1, %lu)",
		    (unsigned long)sizeof *avs);
		return 1;
	}
	avs->phase = phase;

	/* Load the "proposal candidate" attribute set.  */
	(void)attribute_map(xf->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF,
	    GET_ISAKMP_GEN_LENGTH(xf->p) - ISAKMP_TRANSFORM_SA_ATTRS_OFF,
	    sa_validate_xf_attrs, avs);
	xf_id = GET_ISAKMP_TRANSFORM_ID(xf->p);

	/* Check against the transforms we suggested.  */
	avs->mode++;
	for (pa = TAILQ_FIRST(&match->xfs); pa && !found;
	    pa = TAILQ_NEXT(pa, next)) {
		if (xf_id != GET_ISAKMP_TRANSFORM_ID(pa->attrs))
			continue;

		bzero(avs->checked, sizeof avs->checked);
		if (attribute_map(pa->attrs + ISAKMP_TRANSFORM_SA_ATTRS_OFF,
		    pa->len - ISAKMP_TRANSFORM_SA_ATTRS_OFF,
		    sa_validate_xf_attrs, avs) == 0)
			found++;

		LOG_DBG((LOG_SA, 80, "sa_validate_proto_xf: attr_map "
		    "xf %p proto %p pa %p found %d", xf, match, pa, found));

		if (!found)
			continue;

		/*
		 * Require all attributes present and checked.  XXX perhaps
		 * not?
		 */
		for (i = 0; i < sizeof avs->checked; i++)
			if (avs->attrp[i] && !avs->checked[i])
				found = 0;

		LOG_DBG((LOG_SA, 80, "sa_validate_proto_xf: req_attr "
		    "xf %p proto %p pa %p found %d", xf, match, pa, found));
	}
	free(avs);
	return found ? 0 : 1;
}
Пример #2
0
QVariant style::attribute(const QString &a_type, const QString &a_name) const {
  return attribute_map(a_type)[a_name];
}
Пример #3
0
/*
 * As "the server", this starts REQ/REPLY (initiated by the client).
 * As "the client", this starts SET/ACK (initiated by the server).
 */
static int
cfg_responder_recv_ATTR(struct message *msg)
{
	struct payload *attrp = payload_first(msg, ISAKMP_PAYLOAD_ATTRIBUTE);
	struct ipsec_exch *ie = msg->exchange->data;
	struct sa      *isakmp_sa = msg->isakmp_sa;
	struct isakmp_cfg_attr *attr;
	struct sockaddr *sa;
	char           *addr;

	if (msg->exchange->phase == 2)
		if (cfg_verify_hash(msg))
			return -1;

	ie->cfg_id = GET_ISAKMP_ATTRIBUTE_ID(attrp->p);
	ie->cfg_type = attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF];

	switch (ie->cfg_type) {
	case ISAKMP_CFG_REQUEST:
	case ISAKMP_CFG_SET:
		break;

	default:
		message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
		log_print("cfg_responder_recv_ATTR: "
		    "unexpected configuration message type %d", ie->cfg_type);
		return -1;
	}

	attribute_map(attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF,
	    GET_ISAKMP_GEN_LENGTH(attrp->p) - ISAKMP_TRANSFORM_SA_ATTRS_OFF,
	    cfg_decode_attribute, ie);

	switch (ie->cfg_type) {
	case ISAKMP_CFG_REQUEST:
		/* We're done.  */
		break;

	case ISAKMP_CFG_SET: {
			/* SET/ACK -- Client side (SET from server) */
			const char     *uk_addr = "<unknown>";

			msg->transport->vtbl->get_dst(isakmp_sa->transport,
			    &sa);
			if (sockaddr2text(sa, &addr, 0) < 0)
				addr = (char *) uk_addr;

			for (attr = LIST_FIRST(&ie->attrs); attr;
			    attr = LIST_NEXT(attr, link))
				LOG_DBG((LOG_NEGOTIATION, 50,
				    "cfg_responder_recv_ATTR: "
				    "server %s asks us to SET attribute %s",
				    addr, constant_name(isakmp_cfg_attr_cst,
					attr->type)));

			/*
			 * XXX Here's the place to add code to walk through
			 * XXX each attribute and send them along to dhclient
			 * XXX or whatever. Each attribute that we act upon
			 * XXX (such as setting a netmask), should be marked
			 * XXX like this for us to send the proper ACK
			 * XXX response: attr->attr_used++;
			 */

			if (addr != uk_addr)
				free(addr);
		}
		break;

	default:
		break;
	}

	attrp->flags |= PL_MARK;
	return 0;
}
Пример #4
0
/*
 * As "the server", this ends SET/ACK.
 * As "the client", this ends REQ/REPLY.
 */
static int
cfg_initiator_recv_ATTR(struct message *msg)
{
	struct payload *attrp = payload_first(msg, ISAKMP_PAYLOAD_ATTRIBUTE);
	struct ipsec_exch *ie = msg->exchange->data;
	struct sa      *isakmp_sa = msg->isakmp_sa;
	struct isakmp_cfg_attr *attr;
	struct sockaddr *sa;
	const char     *uk_addr = "<unknown>";
	char           *addr;

	if (msg->exchange->phase == 2)
		if (cfg_verify_hash(msg))
			return -1;

	/* Sanity.  */
	if (ie->cfg_id != GET_ISAKMP_ATTRIBUTE_ID(attrp->p)) {
		log_print("cfg_initiator_recv_ATTR: "
		    "cfg packet ID does not match!");
		message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
		return -1;
	}
	switch (attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]) {
	case ISAKMP_CFG_ACK:
		if (ie->cfg_type != ISAKMP_CFG_SET) {
			log_print("cfg_initiator_recv_ATTR: "
			    "bad packet type ACK");
			message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED,
			    0, 1, 0);
			return -1;
		}
		break;
	case ISAKMP_CFG_REPLY:
		if (ie->cfg_type != ISAKMP_CFG_REQUEST) {
			log_print("cfg_initiator_recv_ATTR: "
			    "bad packet type REPLY");
			message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED,
			    0, 1, 0);
			return -1;
		}
		break;

	default:
		log_print("cfg_initiator_recv_ATTR: unexpected configuration "
		    "message type %d", attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]);
		message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
		return -1;
	}

	attribute_map(attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF,
	    GET_ISAKMP_GEN_LENGTH(attrp->p) - ISAKMP_TRANSFORM_SA_ATTRS_OFF,
	    cfg_decode_attribute, ie);

	switch (ie->cfg_type) {
	case ISAKMP_CFG_ACK: {
			/* SET/ACK -- Server side (ACK from client) */
			msg->transport->vtbl->get_src(isakmp_sa->transport,
			    &sa);
			if (sockaddr2text(sa, &addr, 0) < 0)
				addr = (char *) uk_addr;

			for (attr = LIST_FIRST(&ie->attrs); attr;
			    attr = LIST_NEXT(attr, link))
				LOG_DBG((LOG_NEGOTIATION, 50,
				    "cfg_initiator_recv_ATTR: "
				    "client %s ACKs attribute %s", addr,
				    constant_name(isakmp_cfg_attr_cst,
					attr->type)));

			if (addr != uk_addr)
				free(addr);
		}
		break;

	case ISAKMP_CFG_REPLY: {
			/*
			 * REQ/REPLY: effect attributes we've gotten
			 * responses on.
			 */
			msg->transport->vtbl->get_src(isakmp_sa->transport,
			    &sa);
			if (sockaddr2text(sa, &addr, 0) < 0)
				addr = (char *) uk_addr;

			for (attr = LIST_FIRST(&ie->attrs); attr;
			    attr = LIST_NEXT(attr, link))
				LOG_DBG((LOG_NEGOTIATION, 50,
				    "cfg_initiator_recv_ATTR: "
				    "server %s replied with attribute %s",
				    addr, constant_name(isakmp_cfg_attr_cst,
					attr->type)));

			if (addr != uk_addr)
				free(addr);
		}
		break;

	default:
		break;
	}

	attrp->flags |= PL_MARK;
	return 0;
}
Пример #5
0
/* Offer a set of transforms to the responder in the MSG message.  */
int
ike_phase_1_initiator_send_SA (struct message *msg)
{
    struct exchange *exchange = msg->exchange;
    struct ipsec_exch *ie = exchange->data;
    u_int8_t *proposal = 0, *sa_buf = 0, *saved_nextp, *attr;
    u_int8_t **transform = 0;
    size_t transforms_len = 0, proposal_len, sa_len;
    size_t *transform_len = 0;
    struct conf_list *conf, *life_conf;
    struct conf_list_node *xf, *life;
    int i, value, update_nextp;
    struct payload *p;
    struct proto *proto;
    int group_desc = -1, new_group_desc;

    /* Get the list of transforms.  */
    conf = conf_get_list (exchange->policy, "Transforms");
    if (!conf)
        return -1;

    transform = calloc (conf->cnt, sizeof *transform);
    if (!transform)
    {
        log_error ("ike_phase_1_initiator_send_SA: calloc (%d, %lu) failed",
                   conf->cnt, (unsigned long)sizeof *transform);
        goto bail_out;
    }

    transform_len = calloc (conf->cnt, sizeof *transform_len);
    if (!transform_len)
    {
        log_error ("ike_phase_1_initiator_send_SA: calloc (%d, %lu) failed",
                   conf->cnt, (unsigned long)sizeof *transform_len);
        goto bail_out;
    }

    for (xf = TAILQ_FIRST (&conf->fields), i = 0; i < conf->cnt;
            i++, xf = TAILQ_NEXT (xf, link))
    {
        /* XXX The sizing needs to be dynamic.  */
        transform[i]
            = malloc (ISAKMP_TRANSFORM_SA_ATTRS_OFF + 16 * ISAKMP_ATTR_VALUE_OFF);
        if (!transform[i])
        {
            log_error ("ike_phase_1_initiator_send_SA: malloc (%d) failed",
                       ISAKMP_TRANSFORM_SA_ATTRS_OFF
                       + 16 * ISAKMP_ATTR_VALUE_OFF);
            goto bail_out;
        }

        SET_ISAKMP_TRANSFORM_NO (transform[i], i);
        SET_ISAKMP_TRANSFORM_ID (transform[i], IPSEC_TRANSFORM_KEY_IKE);
        SET_ISAKMP_TRANSFORM_RESERVED (transform[i], 0);

        attr = transform[i] + ISAKMP_TRANSFORM_SA_ATTRS_OFF;

        if (attribute_set_constant (xf->field, "ENCRYPTION_ALGORITHM",
                                    ike_encrypt_cst,
                                    IKE_ATTR_ENCRYPTION_ALGORITHM, &attr))
            goto bail_out;

        if (attribute_set_constant (xf->field, "HASH_ALGORITHM", ike_hash_cst,
                                    IKE_ATTR_HASH_ALGORITHM, &attr))
            goto bail_out;

        if (attribute_set_constant (xf->field, "AUTHENTICATION_METHOD",
                                    ike_auth_cst, IKE_ATTR_AUTHENTICATION_METHOD,
                                    &attr))
            goto bail_out;

        if (attribute_set_constant (xf->field, "GROUP_DESCRIPTION",
                                    ike_group_desc_cst,
                                    IKE_ATTR_GROUP_DESCRIPTION, &attr))
        {
            /*
             * If no group description exists, try looking for a user-defined
             * one.
             */
            if (attribute_set_constant (xf->field, "GROUP_TYPE", ike_group_cst,
                                        IKE_ATTR_GROUP_TYPE, &attr))
                goto bail_out;

#if 0
            if (attribute_set_bignum (xf->field, "GROUP_PRIME",
                                      IKE_ATTR_GROUP_PRIME, &attr))
                goto bail_out;

            if (attribute_set_bignum (xf->field, "GROUP_GENERATOR_2",
                                      IKE_ATTR_GROUP_GENERATOR_2, &attr))
                goto bail_out;

            if (attribute_set_bignum (xf->field, "GROUP_GENERATOR_2",
                                      IKE_ATTR_GROUP_GENERATOR_2, &attr))
                goto bail_out;

            if (attribute_set_bignum (xf->field, "GROUP_CURVE_A",
                                      IKE_ATTR_GROUP_CURVE_A, &attr))
                goto bail_out;

            if (attribute_set_bignum (xf->field, "GROUP_CURVE_B",
                                      IKE_ATTR_GROUP_CURVE_B, &attr))
                goto bail_out;
#endif
        }

        /*
         * Life durations are special, we should be able to specify
         * several, one per type.
         */
        life_conf = conf_get_list (xf->field, "Life");
        if (life_conf)
        {
            for (life = TAILQ_FIRST (&life_conf->fields); life;
                    life = TAILQ_NEXT (life, link))
            {
                attribute_set_constant (life->field, "LIFE_TYPE",
                                        ike_duration_cst, IKE_ATTR_LIFE_TYPE,
                                        &attr);

                /* XXX Deals with 16 and 32 bit lifetimes only */
                value = conf_get_num (life->field, "LIFE_DURATION", 0);
                if (value)
                {
                    if (value <= 0xffff)
                        attr = attribute_set_basic (attr, IKE_ATTR_LIFE_DURATION,
                                                    value);
                    else
                    {
                        value = htonl (value);
                        attr = attribute_set_var (attr, IKE_ATTR_LIFE_DURATION,
                                                  (u_int8_t *)&value,
                                                  sizeof value);
                    }
                }
            }
            conf_free_list (life_conf);
        }

        attribute_set_constant (xf->field, "PRF", ike_prf_cst, IKE_ATTR_PRF,
                                &attr);

        value = conf_get_num (xf->field, "KEY_LENGTH", 0);
        if (value)
            attr = attribute_set_basic (attr, IKE_ATTR_KEY_LENGTH, value);

        value = conf_get_num (xf->field, "FIELD_SIZE", 0);
        if (value)
            attr = attribute_set_basic (attr, IKE_ATTR_FIELD_SIZE, value);

        value = conf_get_num (xf->field, "GROUP_ORDER", 0);
        if (value)
            attr = attribute_set_basic (attr, IKE_ATTR_GROUP_ORDER, value);

        /* Record the real transform size.  */
        transforms_len += transform_len[i] = attr - transform[i];

        /* XXX I don't like exchange-specific stuff in here.  */
        if (exchange->type == ISAKMP_EXCH_AGGRESSIVE)
        {
            /*
             * Make sure that if a group description is specified, it is
             * specified for all transforms equally.
             */
            attr = (u_int8_t *)conf_get_str (xf->field, "GROUP_DESCRIPTION");
            new_group_desc
                = attr ? constant_value (ike_group_desc_cst, (char *)attr) : 0;
            if (group_desc == -1)
                group_desc = new_group_desc;
            else if (group_desc != new_group_desc)
            {
                log_print ("ike_phase_1_initiator_send_SA: "
                           "differing group descriptions in a proposal");
                goto bail_out;
            }
        }

        /* We need to check that we actually support our configuration.  */
        if (attribute_map (transform[i] + ISAKMP_TRANSFORM_SA_ATTRS_OFF,
                           transform_len[i] - ISAKMP_TRANSFORM_SA_ATTRS_OFF,
                           exchange->doi->is_attribute_incompatible, msg))
        {
            log_print ("ike_phase_1_initiator_send_SA: "
                       "section [%s] has unsupported attribute(s)",
                       xf->field);
            goto bail_out;
        }
    }

    /* XXX I don't like exchange-specific stuff in here.  */
    if (exchange->type == ISAKMP_EXCH_AGGRESSIVE)
        ie->group = group_get (group_desc);

    proposal_len = ISAKMP_PROP_SPI_OFF;
    proposal = malloc (proposal_len);
    if (!proposal)
    {
        log_error ("ike_phase_1_initiator_send_SA: malloc (%lu) failed",
                   (unsigned long)proposal_len);
        goto bail_out;
    }

    SET_ISAKMP_PROP_NO (proposal, 1);
    SET_ISAKMP_PROP_PROTO (proposal, ISAKMP_PROTO_ISAKMP);
    SET_ISAKMP_PROP_SPI_SZ (proposal, 0);
    SET_ISAKMP_PROP_NTRANSFORMS (proposal, conf->cnt);

    /* XXX I would like to see this factored out.  */
    proto = calloc (1, sizeof *proto);
    if (!proto)
    {
        log_error ("ike_phase_1_initiator_send_SA: calloc (1, %lu) failed",
                   (unsigned long)sizeof *proto);
        goto bail_out;
    }

    proto->no = 1;
    proto->proto = ISAKMP_PROTO_ISAKMP;
    proto->sa = TAILQ_FIRST (&exchange->sa_list);
    TAILQ_INSERT_TAIL (&TAILQ_FIRST (&exchange->sa_list)->protos, proto,
                       link);

    sa_len = ISAKMP_SA_SIT_OFF + IPSEC_SIT_SIT_LEN;
    sa_buf = malloc (sa_len);
    if (!sa_buf)
    {
        log_error ("ike_phase_1_initiator_send_SA: malloc (%lu) failed",
                   (unsigned long)sa_len);
        goto bail_out;
    }

    SET_ISAKMP_SA_DOI (sa_buf, IPSEC_DOI_IPSEC);
    SET_IPSEC_SIT_SIT (sa_buf + ISAKMP_SA_SIT_OFF, IPSEC_SIT_IDENTITY_ONLY);

    /*
     * Add the payloads.  As this is a SA, we need to recompute the
     * lengths of the payloads containing others.
     */
    if (message_add_payload (msg, ISAKMP_PAYLOAD_SA, sa_buf, sa_len, 1))
        goto bail_out;
    SET_ISAKMP_GEN_LENGTH (sa_buf,
                           sa_len + proposal_len + transforms_len);
    sa_buf = 0;

    saved_nextp = msg->nextp;
    if (message_add_payload (msg, ISAKMP_PAYLOAD_PROPOSAL, proposal,
                             proposal_len, 0))
        goto bail_out;
    SET_ISAKMP_GEN_LENGTH (proposal, proposal_len + transforms_len);
    proposal = 0;

    update_nextp = 0;
    for (i = 0; i < conf->cnt; i++)
    {
        if (message_add_payload (msg, ISAKMP_PAYLOAD_TRANSFORM, transform[i],
                                 transform_len[i], update_nextp))
            goto bail_out;
        update_nextp = 1;
        transform[i] = 0;
    }
    msg->nextp = saved_nextp;

    /* Save SA payload body in ie->sa_i_b, length ie->sa_i_b_len.  */
    ie->sa_i_b_len = sa_len + proposal_len + transforms_len - ISAKMP_GEN_SZ;
    ie->sa_i_b = malloc (ie->sa_i_b_len);
    if (!ie->sa_i_b)
    {
        log_error ("ike_phase_1_initiator_send_SA: malloc (%lu) failed",
                   (unsigned long)ie->sa_i_b_len);
        goto bail_out;
    }
    memcpy (ie->sa_i_b,
            TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SA])->p + ISAKMP_GEN_SZ,
            sa_len - ISAKMP_GEN_SZ);
    memcpy (ie->sa_i_b + sa_len - ISAKMP_GEN_SZ,
            TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_PROPOSAL])->p,
            proposal_len);
    transforms_len = 0;
    for (i = 0, p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_TRANSFORM]);
            i < conf->cnt; i++, p = TAILQ_NEXT (p, link))
    {
        memcpy (ie->sa_i_b + sa_len + proposal_len + transforms_len
                - ISAKMP_GEN_SZ,
                p->p, transform_len[i]);
        transforms_len += transform_len[i];
    }

    conf_free_list (conf);
    free (transform);
    free (transform_len);
    return 0;

bail_out:
    if (sa_buf)
        free (sa_buf);
    if (proposal)
        free (proposal);
    if (transform)
    {
        for (i = 0; i < conf->cnt; i++)
            if (transform[i])
                free (transform[i]);
        free (transform);
    }
    if (transform_len)
        free (transform_len);
    conf_free_list (conf);
    return -1;
}
Пример #6
0
/* Validate a proposal inside SA according to EXCHANGE's policy.  */
static int
ike_phase_1_validate_prop (struct exchange *exchange, struct sa *sa,
                           struct sa *isakmp_sa)
{
    struct conf_list *conf, *tags;
    struct conf_list_node *xf, *tag;
    struct proto *proto;
    struct validation_state vs;
    struct attr_node *node, *next_node;

    /* Get the list of transforms.  */
    conf = conf_get_list (exchange->policy, "Transforms");
    if (!conf)
        return 0;

    for (xf = TAILQ_FIRST (&conf->fields); xf; xf = TAILQ_NEXT (xf, link))
    {
        for (proto = TAILQ_FIRST (&sa->protos); proto;
                proto = TAILQ_NEXT (proto, link))
        {
            /* Mark all attributes in our policy as unseen.  */
            LIST_INIT (&vs.attrs);
            vs.xf = xf;
            vs.life = 0;
            if (attribute_map (proto->chosen->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF,
                               GET_ISAKMP_GEN_LENGTH (proto->chosen->p)
                               - ISAKMP_TRANSFORM_SA_ATTRS_OFF,
                               attribute_unacceptable, &vs))
                goto try_next;

            /* Sweep over unseen tags in this section.  */
            tags = conf_get_tag_list (xf->field);
            if (tags)
            {
                for (tag = TAILQ_FIRST (&tags->fields); tag;
                        tag = TAILQ_NEXT (tag, link))
                    /*
                     * XXX Should we care about attributes we have, they do not
                     * provide?
                     */
                    for (node = LIST_FIRST (&vs.attrs); node;
                            node = next_node)
                    {
                        next_node = LIST_NEXT (node, link);
                        if (node->type
                                == constant_value (ike_attr_cst, tag->field))
                        {
                            LIST_REMOVE (node, link);
                            free (node);
                        }
                    }
                conf_free_list (tags);
            }

            /* Are there leftover tags in this section?  */
            node = LIST_FIRST (&vs.attrs);
            if (node)
                goto try_next;
        }

        /* All protocols were OK, we succeeded.  */
        LOG_DBG ((LOG_NEGOTIATION, 20, "ike_phase_1_validate_prop: success"));
        conf_free_list (conf);
        if (vs.life)
            free (vs.life);
        return 1;

try_next:
        /* Are there leftover tags in this section?  */
        node = LIST_FIRST (&vs.attrs);
        while (node)
        {
            LIST_REMOVE (node, link);
            free (node);
            node = LIST_FIRST (&vs.attrs);
        }
        if (vs.life)
            free (vs.life);
    }

    LOG_DBG ((LOG_NEGOTIATION, 20, "ike_phase_1_validate_prop: failure"));
    conf_free_list (conf);
    return 0;
}