summaryrefslogtreecommitdiff
path: root/usr.sbin/tcpdump
diff options
context:
space:
mode:
authorHans-Joerg Hoexer <hshoexer@cvs.openbsd.org>2004-04-13 17:56:55 +0000
committerHans-Joerg Hoexer <hshoexer@cvs.openbsd.org>2004-04-13 17:56:55 +0000
commit82ffd6945096d369c4436c9987f335fa145d3f2d (patch)
tree9801583c9d70ca054383bd24dd5446c68c202cb6 /usr.sbin/tcpdump
parent16155e998b3fac44c07a4f9c266ab50bcf5f7513 (diff)
Cleanup and more careful payload parsing.
ok ho@
Diffstat (limited to 'usr.sbin/tcpdump')
-rw-r--r--usr.sbin/tcpdump/print-ike.c279
1 files changed, 204 insertions, 75 deletions
diff --git a/usr.sbin/tcpdump/print-ike.c b/usr.sbin/tcpdump/print-ike.c
index 7bf81535ca7..8a8f1d9f0ce 100644
--- a/usr.sbin/tcpdump/print-ike.c
+++ b/usr.sbin/tcpdump/print-ike.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: print-ike.c,v 1.21 2004/04/06 08:57:20 ho Exp $ */
+/* $OpenBSD: print-ike.c,v 1.22 2004/04/13 17:56:54 hshoexer Exp $ */
/*
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
@@ -29,7 +29,7 @@
#ifndef lint
static const char rcsid[] =
- "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-ike.c,v 1.21 2004/04/06 08:57:20 ho Exp $ (XXX)";
+ "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-ike.c,v 1.22 2004/04/13 17:56:54 hshoexer Exp $ (XXX)";
#endif
#include <sys/param.h>
@@ -62,6 +62,51 @@ struct isakmp_header {
u_int8_t payloads[0];
};
+struct sa_payload {
+ u_int8_t next_payload;
+ u_int8_t reserved;
+ u_int16_t payload_length;
+ u_int32_t doi;
+ u_int8_t situation[0];
+};
+
+struct proposal_payload {
+ u_int8_t next_payload;
+ u_int8_t reserved;
+ u_int16_t payload_length;
+ u_int8_t nprop;
+ u_int8_t proto;
+ u_int8_t spi_size;
+ u_int8_t nspis;
+ u_int8_t spi[0];
+};
+
+struct transform_payload {
+ u_int8_t next_payload;
+ u_int8_t reserved;
+ u_int16_t payload_length;
+ u_int8_t ntrans;
+ u_int8_t transform;
+ u_int16_t reserved2;
+ u_int8_t attribute[0];
+};
+
+struct ke_payload {
+ u_int8_t next_payload;
+ u_int8_t reserved;
+ u_int16_t payload_length;
+ u_int8_t data[0];
+};
+
+struct id_payload {
+ u_int8_t next_payload;
+ u_int8_t reserved;
+ u_int16_t payload_length;
+ u_int8_t type;
+ u_int8_t id_data[3];
+ u_int8_t data[0];
+};
+
struct notification_payload {
u_int8_t next_payload;
u_int8_t reserved;
@@ -84,6 +129,22 @@ struct delete_payload {
u_int8_t spi[0];
};
+struct vendor_payload {
+ u_int8_t next_payload;
+ u_int8_t reserved;
+ u_int16_t payload_length;
+ u_int8_t vid[0];
+};
+
+struct attribute_payload {
+ u_int8_t next_payload;
+ u_int8_t reserved;
+ u_int16_t payload_length;
+ u_int8_t type;
+ u_int8_t reserved2;
+ u_int16_t id;
+};
+
static void ike_pl_print(u_int8_t, u_int8_t *, u_int8_t);
int ike_tab_level = 0;
@@ -204,20 +265,34 @@ trunc:
void
ike_pl_sa_print (u_int8_t *buf, int len)
{
- u_int32_t situation = ntohl(*(u_int32_t *)(buf + 4));
- u_int8_t ike_doi = ntohl((*(u_int32_t *)buf));
- printf(" DOI: %d", ike_doi);
- if (ike_doi == IPSEC_DOI) {
+ struct sa_payload *sp = (struct sa_payload *)buf;
+ u_int32_t sit_ipsec;
+
+ if (len < sizeof(struct sa_payload)) {
+ printf(" [|payload]");
+ return;
+ }
+
+ sp->doi = ntohl(sp->doi);
+ printf(" DOI: %d", sp->doi);
+
+ if (sp->doi == IPSEC_DOI) {
+ if ((sp->situation + sizeof(u_int32_t)) > (buf + len)) {
+ printf(" [|payload]");
+ return;
+ }
printf("(IPSEC) situation: ");
- if (situation & IKE_SITUATION_IDENTITY_ONLY)
+ sit_ipsec = ntohl(*(u_int32_t *)sp->situation);
+ if (sit_ipsec & IKE_SITUATION_IDENTITY_ONLY)
printf("IDENTITY_ONLY ");
- if (situation & IKE_SITUATION_SECRECY)
+ if (sit_ipsec & IKE_SITUATION_SECRECY)
printf("SECRECY ");
- if (situation & IKE_SITUATION_INTEGRITY)
+ if (sit_ipsec & IKE_SITUATION_INTEGRITY)
printf("INTEGRITY ");
- if ((situation & IKE_SITUATION_MASK) == 0)
- printf("0x%x (unknown)", situation);
- ike_pl_print (PAYLOAD_PROPOSAL, buf + 8, IPSEC_DOI);
+ if ((sit_ipsec & IKE_SITUATION_MASK) == 0)
+ printf("0x%x (unknown)", sit_ipsec);
+ ike_pl_print (PAYLOAD_PROPOSAL, buf +
+ sizeof(struct sa_payload) + sizeof(u_int32_t), IPSEC_DOI);
} else
printf(" situation: (unknown)");
}
@@ -302,87 +377,107 @@ ike_attribute_print (u_int8_t *buf, u_int8_t doi, int maxlen)
void
ike_pl_transform_print (u_int8_t *buf, int len, u_int8_t doi)
{
+ struct transform_payload *tp = (struct transform_payload *)buf;
const char *ah[] = IPSEC_AH_INITIALIZER;
const char *esp[] = IPSEC_ESP_INITIALIZER;
const char *ipcomp[] = IPCOMP_INITIALIZER;
- u_int8_t *attr = buf + 4;
+ u_int8_t *attr = tp->attribute;
+
+ if (len < sizeof(struct transform_payload)) {
+ printf(" [|payload]");
+ return;
+ }
- printf("\n\t%stransform: %u ID: ", ike_tab_offset(), buf[0]);
+ printf("\n\t%stransform: %u ID: ", ike_tab_offset(), tp->ntrans);
switch (doi) {
case ISAKMP_DOI:
- if (buf[1] < (sizeof ike / sizeof ike[0]))
- printf("%s", ike[buf[1]]);
+ if (tp->transform < (sizeof ike / sizeof ike[0]))
+ printf("%s", ike[tp->transform]);
else
- printf("%d(unknown)", buf[1]);
+ printf("%d(unknown)", tp->transform);
break;
default: /* IPSEC_DOI */
- switch (xform_proto) { /* from ike_proposal_print */
+ switch (xform_proto) { /* from ike_proposal_print */
case PROTO_IPSEC_AH:
- if (buf[1] < (sizeof ah / sizeof ah[0]))
- printf("%s", ah[buf[1]]);
+ if (tp->transform < (sizeof ah / sizeof ah[0]))
+ printf("%s", ah[tp->transform]);
else
- printf("%d(unknown)", buf[1]);
+ printf("%d(unknown)", tp->transform);
break;
case PROTO_IPSEC_ESP:
- if (buf[1] < (sizeof esp / sizeof esp[0]))
- printf("%s", esp[buf[1]]);
+ if (tp->transform < (sizeof esp / sizeof esp[0]))
+ printf("%s", esp[tp->transform]);
else
- printf("%d(unknown)", buf[1]);
+ printf("%d(unknown)", tp->transform);
break;
case PROTO_IPCOMP:
- if (buf[1] < (sizeof ipcomp / sizeof ipcomp[0]))
- printf("%s", ipcomp[buf[1]]);
+ if (tp->transform < (sizeof ipcomp / sizeof ipcomp[0]))
+ printf("%s", ipcomp[tp->transform]);
else
- printf("%d(unknown)", buf[1]);
+ printf("%d(unknown)", tp->transform);
break;
default:
- printf("%d(unknown)", buf[1]);
+ printf("%d(unknown)", tp->transform);
}
break;
}
ike_tab_level++;
- while ((int)(attr - buf) < len - 4) /* Skip last 'NONE' attr */
- attr += ike_attribute_print(attr, doi, len - (attr-buf));
+ while ((int)(attr - buf) < len) /* Skip last 'NONE' attr */
+ attr += ike_attribute_print(attr, doi, len - (attr - buf));
ike_tab_level--;
}
void
ike_pl_proposal_print (u_int8_t *buf, int len, u_int8_t doi)
{
- u_int8_t i, p_id = buf[1], spisz = buf[2];
+ struct proposal_payload *pp = (struct proposal_payload *)buf;
+ int i;
+
+ if (len < sizeof(struct proposal_payload)) {
+ printf(" [|payload]");
+ return;
+ }
printf(" proposal: %d proto: %s spisz: %d xforms: %d",
- buf[0], (p_id < (sizeof ike / sizeof ike[0]) ? ike[p_id] :
- "(unknown)"), spisz, buf[3]);
+ pp->nprop, (pp->proto < (sizeof ike / sizeof ike[0]) ?
+ ike[pp->proto] : "(unknown)"), pp->spi_size, pp->nspis);
- /* We need to store this for upcoming ike_attribute_print call. */
- xform_proto = p_id;
+ xform_proto = pp->proto;
- if (spisz) {
- if (p_id == PROTO_IPCOMP)
+ if (pp->spi_size) {
+ if ((pp->spi + pp->spi_size) > (buf + len)) {
+ printf(" [|payload]");
+ return;
+ }
+ if (pp->proto == PROTO_IPCOMP)
printf(" CPI: 0x");
else
printf(" SPI: 0x");
- for (i = 0; i < spisz && (i + 4) < len; i++)
- printf("%02x", buf[i + 4]);
+ for (i = 0; i < pp->spi_size; i++)
+ printf("%02x", pp->spi[i]);
}
/* Reset to sane value. */
- if (p_id == PROTO_ISAKMP)
+ if (pp->proto == PROTO_ISAKMP)
doi = ISAKMP_DOI;
else
doi = IPSEC_DOI;
- if ((char)buf[3] > 0)
- ike_pl_print(PAYLOAD_TRANSFORM, buf + 4 + buf[2], doi);
+ if (pp->nspis > 0)
+ ike_pl_print(PAYLOAD_TRANSFORM, pp->spi + pp->spi_size, doi);
}
void
ike_pl_ke_print (u_int8_t *buf, int len, u_int8_t doi)
{
+ if (len < sizeof(struct ke_payload)) {
+ printf(" [|payload]");
+ return;
+ }
+
if (doi != IPSEC_DOI)
return;
@@ -392,51 +487,77 @@ ike_pl_ke_print (u_int8_t *buf, int len, u_int8_t doi)
void
ipsec_id_print (u_int8_t *buf, int len, u_int8_t doi)
{
+ struct id_payload *ip = (struct id_payload *)buf;
static const char *idtypes[] = IPSEC_ID_TYPE_INITIALIZER;
char ntop_buf[INET6_ADDRSTRLEN];
struct in_addr in;
u_int8_t *p;
+ if (len < sizeof (struct id_payload)) {
+ printf(" [|payload]");
+ return;
+ }
+
if (doi != ISAKMP_DOI)
return;
/* Don't print proto+port unless actually used */
- if (buf[1] | buf[2] | buf[3])
- printf(" proto: %d port: %d", buf[1], (buf[2] << 8) + buf[3]);
+ if (ip->id_data[0] | ip->id_data[1] | ip->id_data[2])
+ printf(" proto: %d port: %d", ip->id_data[0],
+ (ip->id_data[1] << 8) + ip->id_data[2]);
- printf(" type: %s = ", buf[0] < (sizeof idtypes/sizeof idtypes[0]) ?
- idtypes[buf[0]] : "<unknown>");
+ printf(" type: %s = ", ip->type < (sizeof idtypes/sizeof idtypes[0]) ?
+ idtypes[ip->type] : "<unknown>");
- switch (buf[0]) {
+ switch (ip->type) {
case IPSEC_ID_IPV4_ADDR:
- memcpy (&in.s_addr, buf + 4, sizeof in);
+ if ((ip->data + sizeof in) > (buf + len)) {
+ printf(" [|payload]");
+ return;
+ }
+ memcpy (&in.s_addr, ip->data, sizeof in);
printf("%s", inet_ntoa (in));
break;
+
case IPSEC_ID_IPV4_ADDR_SUBNET:
case IPSEC_ID_IPV4_ADDR_RANGE:
- memcpy (&in.s_addr, buf + 4, sizeof in);
+ if ((ip->data + 2 * (sizeof in)) > (buf + len)) {
+ printf(" [|payload]");
+ return;
+ }
+ memcpy (&in.s_addr, ip->data, sizeof in);
printf("%s%s", inet_ntoa (in),
- buf[0] == IPSEC_ID_IPV4_ADDR_SUBNET ? "/" : "-");
- memcpy (&in.s_addr, buf + 8, sizeof in);
+ ip->type == IPSEC_ID_IPV4_ADDR_SUBNET ? "/" : "-");
+ memcpy (&in.s_addr, ip->data + sizeof in, sizeof in);
printf("%s", inet_ntoa (in));
break;
case IPSEC_ID_IPV6_ADDR:
- printf("%s", inet_ntop (AF_INET6, buf + 4, ntop_buf,
+ if ((ip->data + sizeof ntop_buf) > (buf + len)) {
+ printf(" [|payload]");
+ return;
+ }
+ printf("%s", inet_ntop (AF_INET6, ip->data, ntop_buf,
sizeof ntop_buf));
break;
+
case IPSEC_ID_IPV6_ADDR_SUBNET:
case IPSEC_ID_IPV6_ADDR_RANGE:
- printf("%s%s", inet_ntop (AF_INET6, buf + 4, ntop_buf,
+ if ((ip->data + 2 * sizeof ntop_buf) > (buf + len)) {
+ printf(" [|payload]");
+ return;
+ }
+ printf("%s%s", inet_ntop (AF_INET6, ip->data, ntop_buf,
sizeof ntop_buf),
- buf[0] == IPSEC_ID_IPV6_ADDR_SUBNET ? "/" : "-");
- printf("%s", inet_ntop (AF_INET6, buf + 4 + sizeof ntop_buf,
+ ip->type == IPSEC_ID_IPV6_ADDR_SUBNET ? "/" : "-");
+ printf("%s", inet_ntop (AF_INET6, ip->data + sizeof ntop_buf,
ntop_buf, sizeof ntop_buf));
+ break;
case IPSEC_ID_FQDN:
case IPSEC_ID_USER_FQDN:
printf("\"");
- for(p = buf + 4; (int)(p - buf) < len - 4; p++)
+ for (p = ip->data; (int)(p - buf) < len; p++)
printf("%c",(isprint(*p) ? *p : '.'));
printf("\"");
break;
@@ -561,14 +682,20 @@ ike_pl_notification_print (u_int8_t *buf, int len)
void
ike_pl_vendor_print (u_int8_t *buf, int len, u_int8_t doi)
{
- u_int8_t *p = buf;
+ struct vendor_payload *vp = (struct vendor_payload *)buf;
+ u_int8_t *p;
+
+ if (len < sizeof(struct vendor_payload)) {
+ printf(" [|payload]");
+ return;
+ }
if (doi != IPSEC_DOI)
return;
printf(" \"");
- for (p = buf; (int)(p - buf) < len; p++)
- printf("%c",(isprint(*p) ? *p : '.'));
+ for (p = vp->vid; (int)(p - buf) < len; p++)
+ printf("%c", (isprint(*p) ? *p : '.'));
printf("\"");
}
@@ -664,20 +791,22 @@ ike_cfg_attribute_print (u_int8_t *buf, int attr_type, int maxlen)
void
ike_pl_attribute_print (u_int8_t *buf, int len)
{
+ struct attribute_payload *ap = (struct attribute_payload *)buf;
static const char *pl_attr[] = IKE_CFG_ATTRIBUTE_TYPE_INITIALIZER;
- u_int8_t type, *attr;
- u_int16_t id;
+ u_int8_t *attr = buf + sizeof(struct attribute_payload);
- type = buf[0];
- id = buf[2]<<8 | buf[3];
- attr = buf + 4;
+ if (len < sizeof(struct attribute_payload)) {
+ printf(" [|payload]");
+ return;
+ }
printf(" type: %s Id: %d",
- type < (sizeof pl_attr/sizeof pl_attr[0]) ? pl_attr[type] :
- "<unknown>", id);
+ ap->type < (sizeof pl_attr/sizeof pl_attr[0]) ? pl_attr[ap->type] :
+ "<unknown>", ap->id);
- while ((int)(attr - buf) < len - 4)
- attr += ike_cfg_attribute_print(attr, type, len - (attr-buf));
+ while ((int)(attr - buf) < len)
+ attr += ike_cfg_attribute_print(attr, ap->type,
+ len - (attr - buf));
}
void
@@ -704,24 +833,24 @@ ike_pl_print (u_int8_t type, u_int8_t *buf, u_int8_t doi)
return;
case PAYLOAD_SA:
- ike_pl_sa_print(buf+4, this_len);
+ ike_pl_sa_print(buf, this_len);
break;
case PAYLOAD_PROPOSAL:
- ike_pl_proposal_print(buf+4, this_len, doi);
+ ike_pl_proposal_print(buf, this_len, doi);
break;
case PAYLOAD_TRANSFORM:
- ike_pl_transform_print(buf+4, this_len, doi);
+ ike_pl_transform_print(buf, this_len, doi);
break;
case PAYLOAD_KE:
- ike_pl_ke_print(buf+4, this_len, doi);
+ ike_pl_ke_print(buf, this_len, doi);
break;
case PAYLOAD_ID:
/* Should only happen with IPsec DOI */
- ipsec_id_print(buf+4, this_len, doi);
+ ipsec_id_print(buf, this_len, doi);
break;
case PAYLOAD_CERT:
@@ -740,11 +869,11 @@ ike_pl_print (u_int8_t type, u_int8_t *buf, u_int8_t doi)
break;
case PAYLOAD_VENDOR:
- ike_pl_vendor_print(buf+4, this_len, doi);
+ ike_pl_vendor_print(buf, this_len, doi);
break;
case PAYLOAD_ATTRIBUTE:
- ike_pl_attribute_print(buf+4, this_len);
+ ike_pl_attribute_print(buf, this_len);
break;
case PAYLOAD_NAT_D: