int ikev2_msg_valid_ike_sa(struct iked *env, struct ike_header *oldhdr, struct iked_message *msg) { #if 0 /* XXX Disabled, see comment below */ struct iked_message resp; struct ike_header *hdr; struct ikev2_payload *pld; struct ikev2_notify *n; struct ibuf *buf; struct iked_sa sa; #endif if (msg->msg_sa != NULL && msg->msg_policy != NULL) return (0); #if 0 /* * XXX Sending INVALID_IKE_SPIs notifications is disabled * XXX because it is not mandatory and ignored by most * XXX implementations. We might want to enable it in * XXX combination with a rate-limitation to avoid DoS situations. */ /* Fail without error message */ if (msg->msg_response || msg->msg_policy == NULL) return (-1); /* Invalid IKE SA, return notification */ if ((buf = ikev2_msg_init(env, &resp, &msg->msg_peer, msg->msg_peerlen, &msg->msg_local, msg->msg_locallen, 1)) == NULL) goto done; resp.msg_fd = msg->msg_fd; bzero(&sa, sizeof(sa)); if ((oldhdr->ike_flags & IKEV2_FLAG_INITIATOR) == 0) sa.sa_hdr.sh_initiator = 1; sa.sa_hdr.sh_ispi = betoh64(oldhdr->ike_ispi); sa.sa_hdr.sh_rspi = betoh64(oldhdr->ike_rspi); resp.msg_msgid = betoh32(oldhdr->ike_msgid); /* IKE header */ if ((hdr = ikev2_add_header(buf, &sa, resp.msg_msgid, IKEV2_PAYLOAD_NOTIFY, IKEV2_EXCHANGE_INFORMATIONAL, IKEV2_FLAG_RESPONSE)) == NULL) goto done; /* SA payload */ if ((pld = ikev2_add_payload(buf)) == NULL) goto done; if ((n = ibuf_advance(buf, sizeof(*n))) == NULL) goto done; n->n_protoid = IKEV2_SAPROTO_IKE; n->n_spisize = 0; n->n_type = htobe16(IKEV2_N_INVALID_IKE_SPI); if (ikev2_next_payload(pld, sizeof(*n), IKEV2_PAYLOAD_NONE) == -1) goto done; if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) goto done; (void)ikev2_pld_parse(env, hdr, &resp, 0); (void)ikev2_msg_send(env, &resp); done: ikev2_msg_cleanup(env, &resp); #endif /* Always fail */ return (-1); }
int ca_getreq(struct iked *env, struct imsg *imsg) { struct ca_store *store = env->sc_priv; struct iked_sahdr sh; u_int8_t type; u_int8_t *ptr; size_t len; u_int i, n; X509 *ca = NULL, *cert = NULL; struct ibuf *buf; struct iked_static_id id; ptr = (u_int8_t *)imsg->data; len = IMSG_DATA_SIZE(imsg); i = sizeof(id) + sizeof(u_int8_t) + sizeof(sh); if (len < i || ((len - i) % SHA_DIGEST_LENGTH) != 0) return (-1); memcpy(&id, ptr, sizeof(id)); if (id.id_type == IKEV2_ID_NONE) return (-1); memcpy(&sh, ptr + sizeof(id), sizeof(sh)); memcpy(&type, ptr + sizeof(id) + sizeof(sh), sizeof(u_int8_t)); switch (type) { case IKEV2_CERT_RSA_KEY: if (store->ca_pubkey.id_type != type || (buf = store->ca_pubkey.id_buf) == NULL) return (-1); log_debug("%s: using local public key of type %s", __func__, print_map(type, ikev2_cert_map)); break; case IKEV2_CERT_X509_CERT: for (n = 1; i < len; n++, i += SHA_DIGEST_LENGTH) { if ((ca = ca_by_subjectpubkey(store->ca_cas, ptr + i, SHA_DIGEST_LENGTH)) == NULL) continue; log_debug("%s: found CA %s", __func__, ca->name); if ((cert = ca_by_issuer(store->ca_certs, X509_get_subject_name(ca), &id)) != NULL) { /* XXX * should we re-validate our own cert here? */ break; } } if (ca == NULL || cert == NULL) { log_warnx("%s: no valid local certificate found", __func__); type = IKEV2_CERT_NONE; ca_setcert(env, &sh, NULL, type, NULL, 0, PROC_IKEV2); return (0); } log_debug("%s: found local certificate %s", __func__, cert->name); if ((buf = ca_x509_serialize(cert)) == NULL) return (-1); break; default: log_warnx("%s: unknown cert type requested", __func__); return (-1); } ca_setcert(env, &sh, NULL, type, ibuf_data(buf), ibuf_size(buf), PROC_IKEV2); return (0); }