Example #1
0
int
x509_cert_get_subjects(void *scert, int *cnt, u_int8_t ***id,
    u_int32_t **id_len)
{
	X509		*cert = scert;
	X509_NAME	*subject;
	int		type;
	u_int8_t	*altname;
	u_int32_t	altlen;
	u_int8_t	*buf = 0;
	unsigned char	*ubuf;
	int		i;

	*id = 0;
	*id_len = 0;

	/*
	 * XXX There can be a collection of subjectAltNames, but for now I
	 * only return the subjectName and a single subjectAltName, if
	 * present.
	 */
	type = x509_cert_subjectaltname(cert, &altname, &altlen);
	if (!type) {
		*cnt = 1;
		altlen = 0;
	} else
		*cnt = 2;

	*id = calloc(*cnt, sizeof **id);
	if (!*id) {
		log_print("x509_cert_get_subject: malloc (%lu) failed",
		    *cnt * (unsigned long)sizeof **id);
		*cnt = 0;
		goto fail;
	}
	*id_len = calloc(*cnt, sizeof **id_len);
	if (!*id_len) {
		log_print("x509_cert_get_subject: malloc (%lu) failed",
		    *cnt * (unsigned long)sizeof **id_len);
		goto fail;
	}
	/* Stash the subjectName into the first slot.  */
	subject = X509_get_subject_name(cert);
	if (!subject)
		goto fail;

	(*id_len)[0] =
		ISAKMP_ID_DATA_OFF + i2d_X509_NAME(subject, NULL) -
		    ISAKMP_GEN_SZ;
	(*id)[0] = malloc((*id_len)[0]);
	if (!(*id)[0]) {
		log_print("x509_cert_get_subject: malloc (%d) failed",
		    (*id_len)[0]);
		goto fail;
	}
	SET_ISAKMP_ID_TYPE((*id)[0] - ISAKMP_GEN_SZ, IPSEC_ID_DER_ASN1_DN);
	ubuf = (*id)[0] + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
	i2d_X509_NAME(subject, &ubuf);

	if (altlen) {
		/* Stash the subjectAltName into the second slot.  */
		buf = malloc(altlen + ISAKMP_ID_DATA_OFF);
		if (!buf) {
			log_print("x509_cert_get_subject: malloc (%d) failed",
			    altlen + ISAKMP_ID_DATA_OFF);
			goto fail;
		}
		switch (type) {
		case X509v3_DNS_NAME:
			SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_FQDN);
			break;

		case X509v3_RFC_NAME:
			SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_USER_FQDN);
			break;

		case X509v3_IP_ADDR:
			/*
			 * XXX I dislike the numeric constants, but I don't
			 * know what we should use otherwise.
			 */
			switch (altlen) {
			case 4:
				SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_IPV4_ADDR);
				break;

			case 16:
				SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_IPV6_ADDR);
				break;

			default:
				log_print("x509_cert_get_subject: invalid "
				    "subjectAltName IPaddress length %d ",
				    altlen);
				goto fail;
			}
			break;
		}

		SET_IPSEC_ID_PROTO(buf + ISAKMP_ID_DOI_DATA_OFF, 0);
		SET_IPSEC_ID_PORT(buf + ISAKMP_ID_DOI_DATA_OFF, 0);
		memcpy(buf + ISAKMP_ID_DATA_OFF, altname, altlen);

		(*id_len)[1] = ISAKMP_ID_DATA_OFF + altlen - ISAKMP_GEN_SZ;
		(*id)[1] = malloc((*id_len)[1]);
		if (!(*id)[1]) {
			log_print("x509_cert_get_subject: malloc (%d) failed",
			    (*id_len)[1]);
			goto fail;
		}
		memcpy((*id)[1], buf + ISAKMP_GEN_SZ, (*id_len)[1]);

		free(buf);
		buf = 0;
	}
	return 1;

fail:
	for (i = 0; i < *cnt; i++)
		free((*id)[i]);
	free(*id);
	free(*id_len);
	free(buf);
	return 0;
}
Example #2
0
int
ike_phase_1_send_ID (struct message *msg)
{
    struct exchange *exchange = msg->exchange;
    u_int8_t *buf;
    char header[80];
    ssize_t sz;
    struct sockaddr *src;
    int initiator = exchange->initiator;
    u_int8_t **id;
    size_t *id_len;
    char *my_id = 0;
    u_int8_t id_type;

    /* Choose the right fields to fill-in.  */
    id = initiator ? &exchange->id_i : &exchange->id_r;
    id_len = initiator ? &exchange->id_i_len : &exchange->id_r_len;

    if (exchange->name)
        my_id = conf_get_str (exchange->name, "ID");

    if (!my_id)
        my_id = conf_get_str ("General", "Default-phase-1-ID");

    msg->transport->vtbl->get_src (msg->transport, &src);
    sz = my_id ? ipsec_id_size (my_id, &id_type) : sockaddr_addrlen (src);
    if (sz == -1)
        return -1;

    sz += ISAKMP_ID_DATA_OFF;
    buf = malloc (sz);
    if (!buf)
    {
        log_error ("ike_phase_1_send_ID: malloc (%lu) failed",
                   (unsigned long)sz);
        return -1;
    }

    SET_IPSEC_ID_PROTO (buf + ISAKMP_ID_DOI_DATA_OFF, 0);
    SET_IPSEC_ID_PORT (buf + ISAKMP_ID_DOI_DATA_OFF, 0);
    if (my_id)
    {
        SET_ISAKMP_ID_TYPE (buf, id_type);
        switch (id_type)
        {
        case IPSEC_ID_IPV4_ADDR:
        case IPSEC_ID_IPV6_ADDR:
            /* Already in network byteorder.  */
            memcpy (buf + ISAKMP_ID_DATA_OFF, sockaddr_addrdata (src),
                    sockaddr_addrlen (src));
            break;

        case IPSEC_ID_FQDN:
        case IPSEC_ID_USER_FQDN:
        case IPSEC_ID_KEY_ID:
            memcpy (buf + ISAKMP_ID_DATA_OFF, conf_get_str (my_id, "Name"),
                    sz - ISAKMP_ID_DATA_OFF);
            break;

        default:
            log_print ("ike_phase_1_send_ID: unsupported ID type %d", id_type);
            free (buf);
            return -1;
        }
    }
    else
    {
        switch (src->sa_family)
        {
        case AF_INET:
            SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV4_ADDR);
            break;
        case AF_INET6:
            SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV6_ADDR);
            break;
        }
        /* Already in network byteorder.  */
        memcpy (buf + ISAKMP_ID_DATA_OFF, sockaddr_addrdata (src),
                sockaddr_addrlen (src));
    }

    if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, buf, sz, 1))
    {
        free (buf);
        return -1;
    }
    *id_len = sz - ISAKMP_GEN_SZ;
    *id = malloc (*id_len);
    if (!*id)
    {
        log_error ("ike_phase_1_send_ID: malloc (%lu) failed",
                   (unsigned long)*id_len);
        return -1;
    }
    memcpy (*id, buf + ISAKMP_GEN_SZ, *id_len);
    snprintf (header, sizeof header, "ike_phase_1_send_ID: %s",
              constant_name (ipsec_id_cst, GET_ISAKMP_ID_TYPE (buf)));
    LOG_DBG_BUF ((LOG_NEGOTIATION, 40, header, buf + ISAKMP_ID_DATA_OFF,
                  sz - ISAKMP_ID_DATA_OFF));

    return 0;
}