Beispiel #1
0
int
ca_x509_subjectaltname_cmp(X509 *cert, struct iked_static_id *id)
{
	struct iked_id	 sanid;
	char		 idstr[IKED_ID_SIZE];
	int		 ret = -1;

	bzero(&sanid, sizeof(sanid));

	if (ca_x509_subjectaltname(cert, &sanid) != 0)
		return (-1);

	ikev2_print_id(&sanid, idstr, sizeof(idstr));

	/* Compare id types, length and data */
	if ((id->id_type != sanid.id_type) ||
	    ((ssize_t)ibuf_size(sanid.id_buf) !=
	    (id->id_length - id->id_offset)) ||
	    (memcmp(id->id_data + id->id_offset,
	    ibuf_data(sanid.id_buf),
	    ibuf_size(sanid.id_buf)) != 0)) {
		log_debug("%s: %s mismatched", __func__, idstr);
		goto done;
	}

	ret = 0;
 done:
	ibuf_release(sanid.id_buf);
	return (ret);
}
int
ikev2_pld_id(struct iked *env, struct ikev2_payload *pld,
    struct iked_message *msg, size_t offset, size_t left, u_int payload)
{
	u_int8_t			*ptr;
	struct ikev2_id			 id;
	size_t				 len;
	struct iked_id			*idp, idb;
	struct iked_sa			*sa = msg->msg_sa;
	u_int8_t			*msgbuf = ibuf_data(msg->msg_data);
	char				 idstr[IKED_ID_SIZE];

	if (ikev2_validate_id(msg, offset, left, pld, &id))
		return (-1);

	bzero(&idb, sizeof(idb));

	/* Don't strip the Id payload header */
	ptr = msgbuf + offset;
	len = betoh16(pld->pld_length) - sizeof(*pld);

	idb.id_type = id.id_type;
	idb.id_offset = sizeof(id);
	if ((idb.id_buf = ibuf_new(ptr, len)) == NULL)
		return (-1);

	if (ikev2_print_id(&idb, idstr, sizeof(idstr)) == -1) {
		log_debug("%s: malformed id", __func__);
		return (-1);
	}

	log_debug("%s: id %s length %zu", __func__, idstr, len);

	if (!ikev2_msg_frompeer(msg)) {
		ibuf_release(idb.id_buf);
		return (0);
	}

	if (!((sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr) ||
	    (!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDi))) {
		log_debug("%s: unexpected id payload", __func__);
		return (0);
	}

	idp = &msg->msg_parent->msg_id;
	if (idp->id_type) {
		log_debug("%s: duplicate id payload", __func__);
		return (-1);
	}

	idp->id_buf = idb.id_buf;
	idp->id_offset = idb.id_offset;
	idp->id_type = idb.id_type;

	return (0);
}
Beispiel #3
0
int
ca_x509_subjectaltname(X509 *cert, struct iked_id *id)
{
	X509_EXTENSION	*san;
	uint8_t		 sanhdr[4], *data;
	int		 ext, santype, sanlen;
	char		 idstr[IKED_ID_SIZE];

	if ((ext = X509_get_ext_by_NID(cert,
	    NID_subject_alt_name, -1)) == -1 ||
	    ((san = X509_get_ext(cert, ext)) == NULL)) {
		log_debug("%s: did not find subjectAltName in certificate",
		    __func__);
		return (-1);
	}

	if (san->value == NULL || san->value->data == NULL ||
	    san->value->length < (int)sizeof(sanhdr)) {
		log_debug("%s: invalid subjectAltName in certificate",
		    __func__);
		return (-1);
	}

	/* This is partially based on isakmpd's x509 subjectaltname code */
	data = (uint8_t *)san->value->data;
	memcpy(&sanhdr, data, sizeof(sanhdr));
	santype = sanhdr[2] & 0x3f;
	sanlen = sanhdr[3];

	if ((sanlen + (int)sizeof(sanhdr)) > san->value->length) {
		log_debug("%s: invalid subjectAltName length", __func__);
		return (-1);
	}

	switch (santype) {
	case GEN_DNS:
		id->id_type = IKEV2_ID_FQDN;
		break;
	case GEN_EMAIL:
		id->id_type = IKEV2_ID_UFQDN;
		break;
	case GEN_IPADD:
		if (sanlen == 4)
			id->id_type = IKEV2_ID_IPV4;
		else if (sanlen == 16)
			id->id_type = IKEV2_ID_IPV6;
		else {
			log_debug("%s: invalid subjectAltName IP address",
			    __func__);
			return (-1);
		}
		break;
	default:
		log_debug("%s: unsupported subjectAltName type %d",
		    __func__, santype);
		return (-1);
	}

	ibuf_release(id->id_buf);
	if ((id->id_buf = ibuf_new(data + sizeof(sanhdr), sanlen)) == NULL) {
		log_debug("%s: failed to get id buffer", __func__);
		return (-1);
	}
	id->id_offset = 0;

	ikev2_print_id(id, idstr, sizeof(idstr));
	log_debug("%s: %s", __func__, idstr);

	return (0);
}
Beispiel #4
0
int
ca_validate_pubkey(struct iked *env, struct iked_static_id *id,
    void *data, size_t len)
{
	BIO		*rawcert = NULL;
	RSA		*peerrsa = NULL, *localrsa = NULL;
	EVP_PKEY	*peerkey = NULL, *localkey = NULL;
	int		 ret = -1;
	FILE		*fp = NULL;
	char		 idstr[IKED_ID_SIZE];
	char		 file[PATH_MAX];
	struct iked_id	 idp;

	if (len == 0 && data == NULL)
		return (-1);

	switch (id->id_type) {
	case IKEV2_ID_IPV4:
	case IKEV2_ID_FQDN:
	case IKEV2_ID_UFQDN:
	case IKEV2_ID_IPV6:
		break;
	default:
		/* Some types like ASN1_DN will not be mapped to file names */
		return (-1);
	}

	bzero(&idp, sizeof(idp));
	if ((idp.id_buf = ibuf_new(id->id_data, id->id_length)) == NULL)
		goto done;

	idp.id_type = id->id_type;
	idp.id_offset = id->id_offset;
	if (ikev2_print_id(&idp, idstr, sizeof(idstr)) == -1)
		goto done;

	if (len == 0) {
		/* Data is already an public key */
		peerkey = (EVP_PKEY *)data;
	} else {
		if ((rawcert = BIO_new_mem_buf(data, len)) == NULL)
			goto done;

		if ((peerrsa = d2i_RSAPublicKey_bio(rawcert, NULL)) == NULL)
			goto sslerr;
		if ((peerkey = EVP_PKEY_new()) == NULL)
			goto sslerr;
		if (!EVP_PKEY_set1_RSA(peerkey, peerrsa))
			goto sslerr;
	}

	lc_string(idstr);
	if (strlcpy(file, IKED_PUBKEY_DIR, sizeof(file)) >= sizeof(file) ||
	    strlcat(file, idstr, sizeof(file)) >= sizeof(file))
		goto done;

	if ((fp = fopen(file, "r")) == NULL)
		goto done;
	localkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
	if (localkey == NULL) {
		/* reading PKCS #8 failed, try PEM */
		rewind(fp);
		localrsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL);
		fclose(fp);
		if (localrsa == NULL)
			goto sslerr;
		if ((localkey = EVP_PKEY_new()) == NULL)
			goto sslerr;
		if (!EVP_PKEY_set1_RSA(localkey, localrsa))
			goto sslerr;
	} else {
		fclose(fp);
	}
	if (localkey == NULL)
		goto sslerr;

	if (!EVP_PKEY_cmp(peerkey, localkey))
		goto done;

	log_debug("%s: valid public key in file %s", __func__, file);

	ret = 0;
 sslerr:
	if (ret != 0)
		ca_sslerror(__func__);
 done:
	ibuf_release(idp.id_buf);
	if (peerkey != NULL)
		EVP_PKEY_free(peerkey);
	if (localkey != NULL)
		EVP_PKEY_free(localkey);
	if (peerrsa != NULL)
		RSA_free(peerrsa);
	if (localrsa != NULL)
		RSA_free(localrsa);
	if (rawcert != NULL)
		BIO_free(rawcert);

	return (ret);
}