int ikev2_msg_send_encrypt(struct iked *env, struct iked_sa *sa, struct ibuf **ep, uint8_t exchange, uint8_t firstpayload, int response) { struct iked_message resp; struct ike_header *hdr; struct ikev2_payload *pld; struct ibuf *buf, *e = *ep; int ret = -1; if ((buf = ikev2_msg_init(env, &resp, &sa->sa_peer.addr, SS_LEN(&sa->sa_peer.addr), &sa->sa_local.addr, SS_LEN(&sa->sa_local.addr), response)) == NULL) goto done; resp.msg_msgid = response ? sa->sa_msgid : ikev2_msg_id(env, sa); /* IKE header */ if ((hdr = ikev2_add_header(buf, sa, resp.msg_msgid, IKEV2_PAYLOAD_SK, exchange, response ? IKEV2_FLAG_RESPONSE : 0)) == NULL) goto done; if ((pld = ikev2_add_payload(buf)) == NULL) goto done; /* Encrypt message and add as an E payload */ if ((e = ikev2_msg_encrypt(env, sa, e)) == NULL) { log_debug("%s: encryption failed", __func__); goto done; } if (ibuf_cat(buf, e) != 0) goto done; if (ikev2_next_payload(pld, ibuf_size(e), firstpayload) == -1) goto done; if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) goto done; /* Add integrity checksum (HMAC) */ if (ikev2_msg_integr(env, sa, buf) != 0) { log_debug("%s: integrity checksum failed", __func__); goto done; } resp.msg_data = buf; resp.msg_sa = sa; resp.msg_fd = sa->sa_fd; TAILQ_INIT(&resp.msg_proposals); (void)ikev2_pld_parse(env, hdr, &resp, 0); ret = ikev2_msg_send(env, &resp); done: /* e is cleaned up by the calling function */ *ep = e; ikev2_msg_cleanup(env, &resp); return (ret); }
int ikev1_dispatch_ikev2(int fd, struct privsep_proc *p, struct imsg *imsg) { struct iked *env = p->p_env; struct iked_message msg; uint8_t *buf; ssize_t len; switch (imsg->hdr.type) { case IMSG_IKE_MESSAGE: log_debug("%s: message", __func__); IMSG_SIZE_CHECK(imsg, &msg); memcpy(&msg, imsg->data, sizeof(msg)); len = IMSG_DATA_SIZE(imsg) - sizeof(msg); buf = (uint8_t *)imsg->data + sizeof(msg); if (len <= 0 || (msg.msg_data = ibuf_new(buf, len)) == NULL) { log_debug("%s: short message", __func__); return (0); } log_debug("%s: message length %zd", __func__, len); ikev1_recv(env, &msg); ikev2_msg_cleanup(env, &msg); return (0); default: break; } return (-1); }
void ikev2_msg_cb(int fd, short event, void *arg) { struct iked_socket *sock = arg; struct iked *env = sock->sock_env; struct iked_message msg; struct ike_header hdr; u_int32_t natt = 0x00000000; u_int8_t buf[IKED_MSGBUF_MAX]; ssize_t len; off_t off; struct iovec iov[2]; bzero(&msg, sizeof(msg)); bzero(buf, sizeof(buf)); msg.msg_peerlen = sizeof(msg.msg_peer); msg.msg_locallen = sizeof(msg.msg_local); msg.msg_parent = &msg; memcpy(&msg.msg_local, &sock->sock_addr, sizeof(sock->sock_addr)); if ((len = recvfromto(fd, buf, sizeof(buf), 0, (struct sockaddr *)&msg.msg_peer, &msg.msg_peerlen, (struct sockaddr *)&msg.msg_local, &msg.msg_locallen)) < (ssize_t)sizeof(natt)) return; if (socket_getport(&msg.msg_local) == IKED_NATT_PORT) { if (bcmp(&natt, buf, sizeof(natt)) != 0) return; msg.msg_natt = 1; off = sizeof(natt); } else off = 0; if ((size_t)(len - off) <= sizeof(hdr)) return; memcpy(&hdr, buf + off, sizeof(hdr)); if ((msg.msg_data = ibuf_new(buf + off, len - off)) == NULL) return; if (hdr.ike_version == IKEV1_VERSION) { iov[0].iov_base = &msg; iov[0].iov_len = sizeof(msg); iov[1].iov_base = buf; iov[1].iov_len = len; proc_composev_imsg(env, PROC_IKEV1, IMSG_IKE_MESSAGE, -1, iov, 2); goto done; } TAILQ_INIT(&msg.msg_proposals); msg.msg_fd = fd; ikev2_recv(env, &msg); done: ikev2_msg_cleanup(env, &msg); }
void ikev2_msg_dispose(struct iked *env, struct iked_msgqueue *queue, struct iked_message *msg) { TAILQ_REMOVE(queue, msg, msg_entry); timer_del(env, &msg->msg_timer); ikev2_msg_cleanup(env, msg); free(msg); }
void ikev2_msg_cb(int fd, short event, void *arg) { struct iked_socket *sock = arg; struct iked *env = sock->sock_env; struct iked_message msg; struct ike_header hdr; uint32_t natt = 0x00000000; uint8_t buf[IKED_MSGBUF_MAX]; ssize_t len; off_t off; bzero(&msg, sizeof(msg)); bzero(buf, sizeof(buf)); msg.msg_peerlen = sizeof(msg.msg_peer); msg.msg_locallen = sizeof(msg.msg_local); msg.msg_parent = &msg; memcpy(&msg.msg_local, &sock->sock_addr, sizeof(sock->sock_addr)); if ((len = recvfromto(fd, buf, sizeof(buf), 0, (struct sockaddr *)&msg.msg_peer, &msg.msg_peerlen, (struct sockaddr *)&msg.msg_local, &msg.msg_locallen)) < (ssize_t)sizeof(natt)) return; if (socket_getport((struct sockaddr *)&msg.msg_local) == IKED_NATT_PORT) { if (memcmp(&natt, buf, sizeof(natt)) != 0) return; msg.msg_natt = 1; off = sizeof(natt); } else off = 0; if ((size_t)(len - off) <= sizeof(hdr)) return; memcpy(&hdr, buf + off, sizeof(hdr)); if ((msg.msg_data = ibuf_new(buf + off, len - off)) == NULL) return; TAILQ_INIT(&msg.msg_proposals); msg.msg_fd = fd; if (hdr.ike_version == IKEV1_VERSION) ikev1_recv(env, &msg); else ikev2_recv(env, &msg); ikev2_msg_cleanup(env, &msg); }
void ikev1_msg_cb(int fd, short event, void *arg) { struct iked_socket *sock = arg; struct iked *env = sock->sock_env; struct iked_message msg; struct ike_header hdr; uint8_t buf[IKED_MSGBUF_MAX]; size_t len; struct iovec iov[2]; msg.msg_peerlen = sizeof(msg.msg_peer); msg.msg_locallen = sizeof(msg.msg_local); if ((len = recvfromto(fd, buf, sizeof(buf), 0, (struct sockaddr*)&msg.msg_peer, &msg.msg_peerlen, (struct sockaddr*)&msg.msg_local, &msg.msg_locallen)) < 1) return; if ((size_t)len <= sizeof(hdr)) return; memcpy(&hdr, buf, sizeof(hdr)); if ((msg.msg_data = ibuf_new(buf, len)) == NULL) return; if (hdr.ike_version == IKEV2_VERSION) { iov[0].iov_base = &msg; iov[0].iov_len = sizeof(msg); iov[1].iov_base = buf; iov[1].iov_len = len; proc_composev_imsg(&env->sc_ps, PROC_IKEV2, -1, IMSG_IKE_MESSAGE, -1, iov, 2); goto done; } ikev1_recv(env, &msg); done: ikev2_msg_cleanup(env, &msg); }
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) { /* * Only permit informational requests from initiator * on closing SAs (for DELETE). */ if (msg->msg_sa->sa_state == IKEV2_STATE_CLOSING) { if (((oldhdr->ike_flags & (IKEV2_FLAG_INITIATOR|IKEV2_FLAG_RESPONSE)) == IKEV2_FLAG_INITIATOR) && (oldhdr->ike_exchange == IKEV2_EXCHANGE_INFORMATIONAL)) return (0); return (-1); } 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); }