diff options
author | Denis Ovsienko <infrastation@yandex.ru> | 2012-06-11 21:06:00 +0400 |
---|---|---|
committer | Denis Ovsienko <infrastation@yandex.ru> | 2012-06-12 14:10:05 +0400 |
commit | 33808c66905cc32682dfb2b209d507dffa6cd8ff (patch) | |
tree | 6ccad25712873c256f108860e78ad25d06f3b256 /print-rip.c | |
parent | c4830eb85e0eb243eb37212b254433a65333c342 (diff) | |
download | tcpdump-33808c66905cc32682dfb2b209d507dffa6cd8ff.tar.gz |
decode RIPv2 authentication up to RFC4822
This change addresses a few issues in rip_entry_print_v2() and
rip_print():
1. In the case of Simple Password (RFC2453) authentication the last
(16th) character of a password was never printed. Other password
characters were printed regardless of existing isprint() test.
2. In the case of Cryptographic (RFC4822) authentication there were no
details available for fixed-size auth header and variable-size auth
trailer.
3. Depending on particular hash function used, a normal authentication
trailer "RTE" may be 20 or more bytes long. Iteration over packet RTEs
should stop once a trailer is decoded. Exact number of RTEs in a message
cannot be told from message size any more.
Test cases are added for Request and Response messages with Simple
Password, Keyed-MD5, HMAC-SHA-1, HMAC-SHA-256, HMAC-SHA-384 and
HMAC-SHA-512 authentication modes. Earlier test case is updated to match
new "number of routes" output format.
Diffstat (limited to 'print-rip.c')
-rw-r--r-- | print-rip.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/print-rip.c b/print-rip.c index 84f8951c..327f057a 100644 --- a/print-rip.c +++ b/print-rip.c @@ -125,32 +125,40 @@ rip_entry_print_v1(register const struct rip_netinfo *ni) EXTRACT_32BITS(&ni->rip_metric)); } -static void -rip_entry_print_v2(register const struct rip_netinfo *ni) +static unsigned +rip_entry_print_v2(register const struct rip_netinfo *ni, const unsigned remaining) { - register u_char *p; register u_short family; - u_char buf[RIP_AUTHLEN]; family = EXTRACT_16BITS(&ni->rip_family); - if (family == 0xFFFF) { /* 16 bytes authentication ? */ - if (EXTRACT_16BITS(&ni->rip_tag) == 2) { /* simple text authentication ? */ - memcpy(buf, &ni->rip_dest, sizeof(buf)); - buf[sizeof(buf)-1] = '\0'; - for (p = buf; *p; p++) { - if (!isprint(*p)) - break; - } - printf("\n\t Simple Text Authentication data: %s", buf); + if (family == 0xFFFF) { /* variable-sized authentication structures */ + u_int16_t auth_type = EXTRACT_16BITS(&ni->rip_tag); + if (auth_type == 2) { + register u_char *p = (u_char *)&ni->rip_dest; + u_int i = 0; + printf("\n\t Simple Text Authentication data: "); + for (; i < RIP_AUTHLEN; p++, i++) + putchar (isprint(*p) ? *p : '.'); + } else if (auth_type == 3) { + printf("\n\t Auth header:"); + printf(" Packet Len %u,", EXTRACT_16BITS(&ni->rip_dest)); + printf(" Key-ID %u,", *((u_int8_t *)ni + 6)); + printf(" Auth Data Len %u,", *((u_int8_t *)ni + 7)); + printf(" SeqNo %u,", EXTRACT_32BITS(&ni->rip_dest_mask)); + printf(" MBZ %u,", EXTRACT_32BITS(&ni->rip_router)); + printf(" MBZ %u", EXTRACT_32BITS(&ni->rip_metric)); + } else if (auth_type == 1) { + printf("\n\t Auth trailer:"); + print_unknown_data((u_int8_t *)&ni->rip_dest,"\n\t ",remaining); + return remaining; /* AT spans till the packet end */ } else { printf("\n\t Unknown (%u) Authentication data:", EXTRACT_16BITS(&ni->rip_tag)); - print_unknown_data((u_int8_t *)&ni->rip_dest,"\n\t ",RIP_AUTHLEN); + print_unknown_data((u_int8_t *)&ni->rip_dest,"\n\t ",remaining); } } else if (family != BSD_AFNUM_INET && family != 0) { printf("\n\t AFI %s", tok2str(bsd_af_values, "Unknown (%u)", family)); print_unknown_data((u_int8_t *)&ni->rip_tag,"\n\t ",RIP_ROUTELEN-2); - return; } else { /* BSD_AFNUM_INET or AFI 0 */ printf("\n\t AFI %s, %15s/%-2d, tag 0x%04x, metric: %u, next-hop: ", tok2str(bsd_af_values, "%u", family), @@ -163,6 +171,7 @@ rip_entry_print_v2(register const struct rip_netinfo *ni) else printf("self"); } + return sizeof (*ni); } void @@ -171,7 +180,6 @@ rip_print(const u_char *dat, u_int length) register const struct rip *rp; register const struct rip_netinfo *ni; register u_int i, j; - register int trunc; if (snapend < dat) { printf(" [|rip]"); @@ -222,19 +230,20 @@ rip_print(const u_char *dat, u_int length) case RIPCMD_REQUEST: case RIPCMD_RESPONSE: j = length / sizeof(*ni); - printf(", routes: %u",j); - trunc = (i / sizeof(*ni)) != j; + printf(", routes: %u%s", j, rp->rip_vers == 2 ? " or less" : ""); ni = (struct rip_netinfo *)(rp + 1); for (; i >= sizeof(*ni); ++ni) { if (rp->rip_vers == 1) + { rip_entry_print_v1(ni); + i -= sizeof(*ni); + } else if (rp->rip_vers == 2) - rip_entry_print_v2(ni); + i -= rip_entry_print_v2(ni, i); else break; - i -= sizeof(*ni); } - if (trunc) + if (i) printf("[|rip]"); break; |