-/* $OpenBSD: ikev2_pld.c,v 1.64 2017/11/30 12:18:44 patrick Exp $ */
+/* $OpenBSD: ikev2_pld.c,v 1.65 2017/12/04 16:52:16 patrick Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
int ikev2_pld_payloads(struct iked *, struct iked_message *,
size_t, size_t, unsigned int);
int ikev2_validate_sa(struct iked_message *, size_t, size_t,
- struct ikev2_payload *, struct ikev2_sa_proposal *);
+ struct ikev2_sa_proposal *);
int ikev2_pld_sa(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
int ikev2_validate_xform(struct iked_message *, size_t, size_t,
int ikev2_pld_attr(struct iked *, struct ikev2_transform *,
struct iked_message *, size_t, size_t);
int ikev2_validate_ke(struct iked_message *, size_t, size_t,
- struct ikev2_payload *, struct ikev2_keyexchange *);
+ struct ikev2_keyexchange *);
int ikev2_pld_ke(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
int ikev2_validate_id(struct iked_message *, size_t, size_t,
- struct ikev2_payload *, struct ikev2_id *);
+ struct ikev2_id *);
int ikev2_pld_id(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t, unsigned int);
int ikev2_validate_cert(struct iked_message *, size_t, size_t,
- struct ikev2_payload *, struct ikev2_cert *);
+ struct ikev2_cert *);
int ikev2_pld_cert(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
int ikev2_validate_certreq(struct iked_message *, size_t, size_t,
- struct ikev2_payload *, struct ikev2_cert *);
+ struct ikev2_cert *);
int ikev2_pld_certreq(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
-int ikev2_validate_nonce(struct iked_message *, size_t, size_t,
- struct ikev2_payload *);
int ikev2_pld_nonce(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
int ikev2_validate_notify(struct iked_message *, size_t, size_t,
- struct ikev2_payload *, struct ikev2_notify *);
+ struct ikev2_notify *);
int ikev2_pld_notify(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
int ikev2_validate_delete(struct iked_message *, size_t, size_t,
- struct ikev2_payload *, struct ikev2_delete *);
+ struct ikev2_delete *);
int ikev2_pld_delete(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
int ikev2_validate_ts(struct iked_message *, size_t, size_t,
- struct ikev2_payload *, struct ikev2_tsp *);
+ struct ikev2_tsp *);
int ikev2_pld_ts(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t, unsigned int);
int ikev2_validate_auth(struct iked_message *, size_t, size_t,
- struct ikev2_payload *, struct ikev2_auth *);
+ struct ikev2_auth *);
int ikev2_pld_auth(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
int ikev2_pld_e(struct iked *, struct ikev2_payload *,
- struct iked_message *, size_t);
+ struct iked_message *, size_t, size_t);
int ikev2_validate_cp(struct iked_message *, size_t, size_t,
- struct ikev2_payload *, struct ikev2_cp *);
+ struct ikev2_cp *);
int ikev2_pld_cp(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
int ikev2_validate_eap(struct iked_message *, size_t, size_t,
- struct ikev2_payload *, struct eap_header *);
+ struct eap_header *);
int ikev2_pld_eap(struct iked *, struct ikev2_payload *,
struct iked_message *, size_t, size_t);
unsigned int e;
int ret;
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t left;
+ size_t total, left;
/* Check if message was decrypted in an E payload */
e = msg->msg_e ? IKED_E : 0;
- while (payload != 0 && offset < length) {
- /* Bytes left in datagram. */
- left = length - offset;
+ /* Bytes left in datagram. */
+ total = length - offset;
- if (ikev2_validate_pld(msg, offset, left, &pld))
+ while (payload != 0 && offset < length) {
+ if (ikev2_validate_pld(msg, offset, total, &pld))
return (-1);
log_debug("%s: %spayload %s"
/* Skip over generic payload header. */
offset += sizeof(pld);
- left -= sizeof(pld);
+ total -= sizeof(pld);
+ left = betoh16(pld.pld_length) - sizeof(pld);
ret = 0;
switch (payload | e) {
payload);
break;
case IKEV2_PAYLOAD_SK:
- ret = ikev2_pld_e(env, &pld, msg, offset);
+ ret = ikev2_pld_e(env, &pld, msg, offset, left);
break;
case IKEV2_PAYLOAD_CP | IKED_E:
ret = ikev2_pld_cp(env, &pld, msg, offset, left);
return (0);
payload = pld.pld_nextpayload;
- offset += betoh16(pld.pld_length) - sizeof(pld);
+ offset += left;
+ total -= left;
}
return (0);
int
ikev2_validate_sa(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld, struct ikev2_sa_proposal *sap)
+ struct ikev2_sa_proposal *sap)
{
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t pld_length, sap_length;
+ size_t sap_length;
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld) + sizeof(*sap)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld) + sizeof(*sap));
- return (-1);
- }
-
- /* This will actually be caught by earlier checks. */
if (left < sizeof(*sap)) {
log_debug("%s: malformed payload: too short for header "
"(%zu < %zu)", __func__, left, sizeof(*sap));
* NB: There might be more proposals, we parse only the first one.
* This condition must never be true.
*/
- if (pld_length - sizeof(*pld) < sap_length) {
+ if (left < sap_length) {
log_debug("%s: payload malformed: SA payload length mismatches "
"proposal substructure length (%lu < %zu)", __func__,
- pld_length - sizeof(*pld), sap_length);
+ left, sap_length);
return (-1);
}
/*
* If there is only one proposal, sap_length must be the
* total payload size.
*/
- if (!sap->sap_more && ((pld_length - sizeof(*pld)) != sap_length)) {
+ if (!sap->sap_more && left != sap_length) {
log_debug("%s: payload malformed: SA payload length mismatches "
"single proposal substructure length (%lu != %zu)",
- __func__, pld_length - sizeof(*pld), sap_length);
+ __func__, left, sap_length);
return (-1);
}
/*
* If there are more than one proposal, there must be bytes
* left in the payload.
*/
- if (sap->sap_more && ((pld_length - sizeof(*pld)) <= sap_length)) {
+ if (sap->sap_more && left <= sap_length) {
log_debug("%s: payload malformed: SA payload too small for "
"further proposals (%zu <= %zu)", __func__,
- pld_length - sizeof(*pld), sap_length);
+ left, sap_length);
return (-1);
}
return (0);
struct iked_proposals *props;
size_t total;
- if (ikev2_validate_sa(msg, offset, left, pld, &sap))
+ if (ikev2_validate_sa(msg, offset, left, &sap))
return (-1);
if (sap.sap_more)
int
ikev2_validate_ke(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld, struct ikev2_keyexchange *kex)
+ struct ikev2_keyexchange *kex)
{
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t pld_length;
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld) + sizeof(*kex)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld) + sizeof(*kex));
- return (-1);
- }
-
- /* This will actually be caught by earlier checks. */
if (left < sizeof(*kex)) {
log_debug("%s: malformed payload: too short for header "
"(%zu < %zu)", __func__, left, sizeof(*kex));
size_t len;
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- if (ikev2_validate_ke(msg, offset, left, pld, &kex))
+ if (ikev2_validate_ke(msg, offset, left, &kex))
return (-1);
log_debug("%s: dh group %s reserved %d", __func__,
betoh16(kex.kex_reserved));
buf = msgbuf + offset + sizeof(kex);
- len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(kex);
+ len = left - sizeof(kex);
if (len == 0) {
log_debug("%s: malformed payload: no KE data given", __func__);
return (-1);
}
- /* This will actually be caught by earlier checks. */
- if (left < len) {
- log_debug("%s: malformed payload: smaller than specified "
- "(%zu < %zu)", __func__, left, len);
- return (-1);
- }
print_hex(buf, 0, len);
int
ikev2_validate_id(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld, struct ikev2_id *id)
+ struct ikev2_id *id)
{
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t pld_length;
-
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld) + sizeof(*id)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld) + sizeof(*id));
- return (-1);
- }
- /* This will actually be caught by earlier checks. */
if (left < sizeof(*id)) {
log_debug("%s: malformed payload: too short for header "
"(%zu < %zu)", __func__, left, sizeof(*id));
uint8_t *msgbuf = ibuf_data(msg->msg_data);
char idstr[IKED_ID_SIZE];
- if (ikev2_validate_id(msg, offset, left, pld, &id))
+ if (ikev2_validate_id(msg, offset, left, &id))
return (-1);
bzero(&idb, sizeof(idb));
/* Don't strip the Id payload header */
ptr = msgbuf + offset;
- len = betoh16(pld->pld_length) - sizeof(*pld);
+ len = left;
idb.id_type = id.id_type;
idb.id_offset = sizeof(id);
int
ikev2_validate_cert(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld, struct ikev2_cert *cert)
+ struct ikev2_cert *cert)
{
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t pld_length;
-
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld) + sizeof(*cert)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld) + sizeof(*cert));
- return (-1);
- }
- /* This will actually be caught by earlier checks. */
if (left < sizeof(*cert)) {
log_debug("%s: malformed payload: too short for header "
"(%zu < %zu)", __func__, left, sizeof(*cert));
struct iked_id *certid;
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- if (ikev2_validate_cert(msg, offset, left, pld, &cert))
+ if (ikev2_validate_cert(msg, offset, left, &cert))
return (-1);
offset += sizeof(cert);
buf = msgbuf + offset;
- len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cert);
+ len = left - sizeof(cert);
log_debug("%s: type %s length %zu",
__func__, print_map(cert.cert_type, ikev2_cert_map), len);
int
ikev2_validate_certreq(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld, struct ikev2_cert *cert)
+ struct ikev2_cert *cert)
{
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t pld_length;
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld) + sizeof(*cert)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld) + sizeof(*cert));
- return (-1);
- }
-
- /* This will actually be caught by earlier checks. */
if (left < sizeof(*cert)) {
log_debug("%s: malformed payload: too short for header "
"(%zu < %zu)", __func__, left, sizeof(*cert));
ssize_t len;
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- if (ikev2_validate_certreq(msg, offset, left, pld, &cert))
+ if (ikev2_validate_certreq(msg, offset, left, &cert))
return (-1);
offset += sizeof(cert);
buf = msgbuf + offset;
- len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cert);
+ len = left - sizeof(cert);
log_debug("%s: type %s length %zd",
__func__, print_map(cert.cert_type, ikev2_cert_map), len);
- /* This will actually be caught by earlier checks. */
- if (len < 0) {
- log_debug("%s: invalid certificate request length", __func__);
- return (-1);
- }
-
print_hex(buf, 0, len);
if (!ikev2_msg_frompeer(msg))
int
ikev2_validate_auth(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld, struct ikev2_auth *auth)
+ struct ikev2_auth *auth)
{
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t pld_length;
-
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld) + sizeof(*auth)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld) + sizeof(*auth));
- return (-1);
- }
- /* This will actually be caught by earlier checks. */
if (left < sizeof(*auth)) {
log_debug("%s: malformed payload: too short for header "
"(%zu < %zu)", __func__, left, sizeof(*auth));
struct iked_sa *sa = msg->msg_sa;
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- if (ikev2_validate_auth(msg, offset, left, pld, &auth))
+ if (ikev2_validate_auth(msg, offset, left, &auth))
return (-1);
offset += sizeof(auth);
buf = msgbuf + offset;
- len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(auth);
+ len = left - sizeof(auth);
log_debug("%s: method %s length %zu",
__func__, print_map(auth.auth_method, ikev2_auth_map), len);
return (0);
}
-int
-ikev2_validate_nonce(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld)
-{
- size_t pld_length;
-
- /* This will actually be caught by earlier checks. */
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld));
- return (-1);
- }
-
- return (0);
-}
-
int
ikev2_pld_nonce(struct iked *env, struct ikev2_payload *pld,
struct iked_message *msg, size_t offset, size_t left)
uint8_t *buf;
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- if (ikev2_validate_nonce(msg, offset, left, pld))
- return (-1);
-
buf = msgbuf + offset;
- len = betoh16(pld->pld_length) - sizeof(*pld);
+ len = left;
if (len == 0) {
log_debug("%s: malformed payload: no NONCE given", __func__);
return (-1);
}
- /* This will actually be caught by earlier checks. */
- if (left < len) {
- log_debug("%s: malformed payload: smaller than specified "
- "(%zu < %zu)", __func__, left, len);
- return (-1);
- }
print_hex(buf, 0, len);
int
ikev2_validate_notify(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld, struct ikev2_notify *n)
+ struct ikev2_notify *n)
{
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t pld_length;
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld) + sizeof(*n)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld) + sizeof(*n));
- return (-1);
- }
-
- /* This will actually be caught by earlier checks. */
if (left < sizeof(*n)) {
log_debug("%s: malformed payload: too short for header "
"(%zu < %zu)", __func__, left, sizeof(*n));
uint16_t signature_hash;
uint8_t transform;
- if (ikev2_validate_notify(msg, offset, left, pld, &n))
+ if (ikev2_validate_notify(msg, offset, left, &n))
return (-1);
type = betoh16(n.n_type);
print_map(n.n_protoid, ikev2_saproto_map), n.n_spisize,
print_map(type, ikev2_n_map));
- len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(n);
+ len = left - sizeof(n);
if ((buf = ibuf_seek(msg->msg_data, offset + sizeof(n), len)) == NULL)
return (-1);
int
ikev2_validate_delete(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld, struct ikev2_delete *del)
+ struct ikev2_delete *del)
{
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t pld_length;
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld) + sizeof(*del)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld) + sizeof(*del));
- return (-1);
- }
-
- /* This will actually be caught by earlier checks. */
if (left < sizeof(*del)) {
log_debug("%s: malformed payload: too short for header "
"(%zu < %zu)", __func__, left, sizeof(*del));
msg->msg_parent->msg_response)
return (0);
- if (ikev2_validate_delete(msg, offset, left, pld, &del))
+ if (ikev2_validate_delete(msg, offset, left, &del))
return (-1);
cnt = betoh16(del.del_nspi);
sz = del.del_spisize;
sz, cnt);
buf = msgbuf + offset + sizeof(del);
- len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(del);
+ len = left - sizeof(del);
print_hex(buf, 0, len);
int
ikev2_validate_ts(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld, struct ikev2_tsp *tsp)
+ struct ikev2_tsp *tsp)
{
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t pld_length;
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld) + sizeof(*tsp)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld) + sizeof(*tsp));
- return (-1);
- }
-
- /* This will actually be caught by earlier checks. */
if (left < sizeof(*tsp)) {
log_debug("%s: malformed payload: too short for header "
"(%zu < %zu)", __func__, left, sizeof(*tsp));
uint8_t buf[2][128];
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- if (ikev2_validate_ts(msg, offset, left, pld, &tsp))
+ if (ikev2_validate_ts(msg, offset, left, &tsp))
return (-1);
offset += sizeof(tsp);
- len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(tsp);
+ len = left - sizeof(tsp);
log_debug("%s: count %d length %zu", __func__,
tsp.tsp_count, len);
int
ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,
- struct iked_message *msg, size_t offset)
+ struct iked_message *msg, size_t offset, size_t left)
{
struct iked_sa *sa = msg->msg_sa;
struct ibuf *e = NULL;
int ret = -1;
buf = msgbuf + offset;
- len = betoh16(pld->pld_length) - sizeof(*pld);
+ len = left;
if ((e = ibuf_new(buf, len)) == NULL)
goto done;
int
ikev2_validate_cp(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld, struct ikev2_cp *cp)
+ struct ikev2_cp *cp)
{
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t pld_length;
-
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld) + sizeof(*cp)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld) + sizeof(*cp));
- return (-1);
- }
- /* This will actually be caught by earlier checks. */
if (left < sizeof(*cp)) {
log_debug("%s: malformed payload: too short for header "
"(%zu < %zu)", __func__, left, sizeof(*cp));
uint8_t *msgbuf = ibuf_data(msg->msg_data);
struct iked_sa *sa = msg->msg_sa;
- if (ikev2_validate_cp(msg, offset, left, pld, &cp))
+ if (ikev2_validate_cp(msg, offset, left, &cp))
return (-1);
offset += sizeof(cp);
buf = msgbuf + offset;
- len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cp);
+ len = left - sizeof(cp);
log_debug("%s: type %s length %zu",
__func__, print_map(cp.cp_type, ikev2_cp_map), len);
int
ikev2_validate_eap(struct iked_message *msg, size_t offset, size_t left,
- struct ikev2_payload *pld, struct eap_header *hdr)
+ struct eap_header *hdr)
{
uint8_t *msgbuf = ibuf_data(msg->msg_data);
- size_t pld_length;
-
- pld_length = betoh16(pld->pld_length);
- if (pld_length < sizeof(*pld) + sizeof(*hdr)) {
- log_debug("%s: malformed payload: specified length smaller "
- "than minimum size (%zu < %zu)", __func__, pld_length,
- sizeof(*pld) + sizeof(*hdr));
- return (-1);
- }
- /* This will actually be caught by earlier checks. */
if (left < sizeof(*hdr)) {
log_debug("%s: malformed payload: too short for header "
"(%zu < %zu)", __func__, left, sizeof(*hdr));
struct iked_sa *sa = msg->msg_sa;
size_t len;
- if (ikev2_validate_eap(msg, offset, left, pld, &hdr))
+ if (ikev2_validate_eap(msg, offset, left, &hdr))
return (-1);
len = betoh16(hdr.eap_length);