add python/ipaddress-1.0.18
[unleashed-userland.git] / components / quagga / patches / 07-cve-2012-0249.patch
blobb6bcd98e795ff6d1ba9ae25f59f67629bbe7b81d
1 The following patches are pulled directly from the GIT repository
2 for the quagga community. They fix the following CVEs:
4 CVE-2012-0249
5 CVE-2012-0250
6 CVE-2012-0255
8 All of the patched CVEs are included in Quagga 0.99.20.1. This patch
9 file can be removed if Quagga is upgraded to that version.
13 From 5861739f8c38bc36ea9955e5cb2be2bf2f482d70 Mon Sep 17 00:00:00 2001
14 From: Paul Jakma <paul@quagga.net>
15 Date: Mon, 09 Jan 2012 20:59:26 +0000
16 Subject: bgpd: Open option parse errors don't NOTIFY, resulting in abort & DoS
18 * bgp_packet.c: (bgp_open_receive) Errors from bgp_open_option_parse are
19 detected, and the code will stop processing the OPEN and return. However
20 it does so without calling bgp_notify_send to send a NOTIFY - which means
21 the peer FSM doesn't get stopped, and bgp_read will be called again later.
22 Because it returns, it doesn't go through the code near the end of the
23 function that removes the current message from the peer input streaam.
24 Thus the next call to bgp_read will try to parse a half-parsed stream as
25 if it were a new BGP message, leading to an assert later in the code when
26 it tries to read stuff that isn't there. Add the required call to
27 bgp_notify_send before returning.
28 * bgp_open.c: (bgp_capability_as4) Be a bit stricter, check the length field
29 corresponds to the only value it can be, which is the amount we're going to
30 read off the stream. And make sure the capability flag gets set, so
31 callers can know this capability was read, regardless.
32 (peek_for_as4_capability) Let bgp_capability_as4 do the length check.
33 ---
34 diff --git bgpd/bgp_open.c bgpd/bgp_open.c
35 index 82deb3d..b5b50bb 100644
36 --- bgpd/bgp_open.c
37 +++ bgpd/bgp_open.c
38 @@ -421,13 +421,20 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
39 static as_t
40 bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
42 + SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
44 + if (hdr->length != CAPABILITY_CODE_AS4_LEN)
45 + {
46 + zlog_err ("%s AS4 capability has incorrect data length %d",
47 + peer->host, hdr->length);
48 + return 0;
49 + }
51 as_t as4 = stream_getl (BGP_INPUT(peer));
53 if (BGP_DEBUG (as4, AS4))
54 zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
55 peer->host, as4);
56 - SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
58 return as4;
61 @@ -689,9 +696,6 @@ peek_for_as4_capability (struct peer *peer, u_char length)
63 if (hdr.code == CAPABILITY_CODE_AS4)
65 - if (hdr.length != CAPABILITY_CODE_AS4_LEN)
66 - goto end;
68 if (BGP_DEBUG (as4, AS4))
69 zlog_info ("[AS4] found AS4 capability, about to parse");
70 as4 = bgp_capability_as4 (peer, &hdr);
71 diff --git bgpd/bgp_packet.c bgpd/bgp_packet.c
72 index f5a74d1..5d8087a 100644
73 --- bgpd/bgp_packet.c
74 +++ bgpd/bgp_packet.c
75 @@ -1459,9 +1459,13 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
76 /* Open option part parse. */
77 if (optlen != 0)
79 - ret = bgp_open_option_parse (peer, optlen, &capability);
80 - if (ret < 0)
81 - return ret;
82 + if ((ret = bgp_open_option_parse (peer, optlen, &capability)) < 0)
83 + {
84 + bgp_notify_send (peer,
85 + BGP_NOTIFY_OPEN_ERR,
86 + BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
87 + return ret;
88 + }
90 else
93 cgit v0.9.0.2
94 From 393b2d64dc0625ba8e01e9e1516efac06d13072e Mon Sep 17 00:00:00 2001
95 From: Denis Ovsienko <infrastation@yandex.ru>
96 Date: Sun, 15 Jan 2012 15:12:19 +0000
97 Subject: ospfd: use LOOKUP() for ospf_packet_type_str
99 * ospf_packet.h: add proper str/max extern declarations
100 * ospf_packet.c
101 * ospf_packet_type_str: rewrite in "struct message", add max value
102 * ospf_packet_add(): use LOOKUP()
103 * ospf_write(): ditto
104 * ospf_hello(): ditto
105 * ospf_read(): ditto
106 * ospf_dump.h: the declaration does not belong here
107 * ospf_dump.c
108 * ospf_header_dump(): use LOOKUP()
109 * show_debugging_ospf(): ditto
111 diff --git ospfd/ospf_dump.c ospfd/ospf_dump.c
112 index e65b2e3..8ace095 100644
113 --- ospfd/ospf_dump.c
114 +++ ospfd/ospf_dump.c
115 @@ -661,7 +661,7 @@ ospf_header_dump (struct ospf_header *ospfh)
116 zlog_debug ("Header");
117 zlog_debug (" Version %d", ospfh->version);
118 zlog_debug (" Type %d (%s)", ospfh->type,
119 - ospf_packet_type_str[ospfh->type]);
120 + LOOKUP (ospf_packet_type_str, ospfh->type));
121 zlog_debug (" Packet Len %d", ntohs (ospfh->length));
122 zlog_debug (" Router ID %s", inet_ntoa (ospfh->router_id));
123 zlog_debug (" Area ID %s", inet_ntoa (ospfh->area_id));
124 @@ -1457,7 +1457,7 @@ DEFUN (show_debugging_ospf,
125 if (IS_DEBUG_OSPF_PACKET (i, SEND) && IS_DEBUG_OSPF_PACKET (i, RECV))
127 vty_out (vty, " OSPF packet %s%s debugging is on%s",
128 - ospf_packet_type_str[i + 1],
129 + LOOKUP (ospf_packet_type_str, i + 1),
130 IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "",
131 VTY_NEWLINE);
133 @@ -1465,12 +1465,12 @@ DEFUN (show_debugging_ospf,
135 if (IS_DEBUG_OSPF_PACKET (i, SEND))
136 vty_out (vty, " OSPF packet %s send%s debugging is on%s",
137 - ospf_packet_type_str[i + 1],
138 + LOOKUP (ospf_packet_type_str, i + 1),
139 IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "",
140 VTY_NEWLINE);
141 if (IS_DEBUG_OSPF_PACKET (i, RECV))
142 vty_out (vty, " OSPF packet %s receive%s debugging is on%s",
143 - ospf_packet_type_str[i + 1],
144 + LOOKUP (ospf_packet_type_str, i + 1),
145 IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "",
146 VTY_NEWLINE);
148 diff --git ospfd/ospf_dump.h ospfd/ospf_dump.h
149 index fb81371..455214f 100644
150 --- ospfd/ospf_dump.h
151 +++ ospfd/ospf_dump.h
152 @@ -121,7 +121,6 @@ extern unsigned long term_debug_ospf_zebra;
153 extern unsigned long term_debug_ospf_nssa;
155 /* Message Strings. */
156 -extern const char *ospf_packet_type_str[];
157 extern char *ospf_lsa_type_str[];
159 /* Prototypes. */
160 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
161 index 0f338d3..03e6d2a 100644
162 --- ospfd/ospf_packet.c
163 +++ ospfd/ospf_packet.c
164 @@ -50,15 +50,16 @@
165 #include "ospfd/ospf_dump.h"
167 /* Packet Type String. */
168 -const char *ospf_packet_type_str[] =
170 - "unknown",
171 - "Hello",
172 - "Database Description",
173 - "Link State Request",
174 - "Link State Update",
175 - "Link State Acknowledgment",
176 +const struct message ospf_packet_type_str[] =
178 + { OSPF_MSG_HELLO, "Hello" },
179 + { OSPF_MSG_DB_DESC, "Database Description" },
180 + { OSPF_MSG_LS_REQ, "Link State Request" },
181 + { OSPF_MSG_LS_UPD, "Link State Update" },
182 + { OSPF_MSG_LS_ACK, "Link State Acknowledgment" },
184 +const size_t ospf_packet_type_str_max = sizeof (ospf_packet_type_str) /
185 + sizeof (ospf_packet_type_str[0]);
187 /* OSPF authentication checking function */
188 static int
189 @@ -201,7 +202,7 @@ ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
190 "destination %s) called with NULL obuf, ignoring "
191 "(please report this bug)!\n",
192 IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
193 - ospf_packet_type_str[stream_getc_from(op->s, 1)],
194 + LOOKUP (ospf_packet_type_str, stream_getc_from(op->s, 1)),
195 inet_ntoa (op->dst));
196 return;
198 @@ -755,7 +756,7 @@ ospf_write (struct thread *thread)
201 zlog_debug ("%s sent to [%s] via [%s].",
202 - ospf_packet_type_str[type], inet_ntoa (op->dst),
203 + LOOKUP (ospf_packet_type_str, type), inet_ntoa (op->dst),
204 IF_NAME (oi));
206 if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
207 @@ -801,7 +802,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
209 zlog_debug ("ospf_header[%s/%s]: selforiginated, "
210 "dropping.",
211 - ospf_packet_type_str[ospfh->type],
212 + LOOKUP (ospf_packet_type_str, ospfh->type),
213 inet_ntoa (iph->ip_src));
215 return;
216 @@ -2571,7 +2572,7 @@ ospf_read (struct thread *thread)
219 zlog_debug ("%s received from [%s] via [%s]",
220 - ospf_packet_type_str[ospfh->type],
221 + LOOKUP (ospf_packet_type_str, ospfh->type),
222 inet_ntoa (ospfh->router_id), IF_NAME (oi));
223 zlog_debug (" src [%s],", inet_ntoa (iph->ip_src));
224 zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst));
225 diff --git ospfd/ospf_packet.h ospfd/ospf_packet.h
226 index 9a47208..2115f11 100644
227 --- ospfd/ospf_packet.h
228 +++ ospfd/ospf_packet.h
229 @@ -163,4 +163,7 @@ extern int ospf_ls_ack_timer (struct thread *);
230 extern int ospf_poll_timer (struct thread *);
231 extern int ospf_hello_reply_timer (struct thread *);
233 +extern const struct message ospf_packet_type_str[];
234 +extern const size_t ospf_packet_type_str_max;
236 #endif /* _ZEBRA_OSPF_PACKET_H */
238 cgit v0.9.0.2
239 From 099ed6744881e71957f2bfeebc4c0727714d2394 Mon Sep 17 00:00:00 2001
240 From: Denis Ovsienko <infrastation@yandex.ru>
241 Date: Fri, 20 Jan 2012 18:32:10 +0000
242 Subject: ospfd: fix ospf_packet_add_top() to use LOOKUP()
245 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
246 index 03e6d2a..500f245 100644
247 --- ospfd/ospf_packet.c
248 +++ ospfd/ospf_packet.c
249 @@ -223,7 +223,7 @@ ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op)
250 "destination %s) called with NULL obuf, ignoring "
251 "(please report this bug)!\n",
252 IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
253 - ospf_packet_type_str[stream_getc_from(op->s, 1)],
254 + LOOKUP (ospf_packet_type_str, stream_getc_from(op->s, 1)),
255 inet_ntoa (op->dst));
256 return;
259 cgit v0.9.0.2
260 From 3092cd57fb44c8293995d013bd86937d1a91745f Mon Sep 17 00:00:00 2001
261 From: Denis Ovsienko <infrastation@yandex.ru>
262 Date: Mon, 30 Jan 2012 11:41:39 +0000
263 Subject: ospfd: introduce ospf_packet_minlen[] (BZ#705)
265 This commit ports some of the OSPFv3 packet reception checks
266 to OSPFv2.
268 * ospf_packet.c
269 * ospf_packet_minlen[]: a direct equivalent of ospf6_packet_minlen[]
270 * ospf_packet_examin(): new function designed after the first part
271 of ospf6_packet_examin()
272 * ospf_read(): verify received packet with ospf_packet_examin()
273 * ospf_packet.h: add convenience macros
275 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
276 index 500f245..f425da8 100644
277 --- ospfd/ospf_packet.c
278 +++ ospfd/ospf_packet.c
279 @@ -61,6 +61,18 @@ const struct message ospf_packet_type_str[] =
280 const size_t ospf_packet_type_str_max = sizeof (ospf_packet_type_str) /
281 sizeof (ospf_packet_type_str[0]);
283 +/* Minimum (besides OSPF_HEADER_SIZE) lengths for OSPF packets of
284 + particular types, offset is the "type" field of a packet. */
285 +static const u_int16_t ospf_packet_minlen[] =
287 + 0,
288 + OSPF_HELLO_MIN_SIZE,
289 + OSPF_DB_DESC_MIN_SIZE,
290 + OSPF_LS_REQ_MIN_SIZE,
291 + OSPF_LS_UPD_MIN_SIZE,
292 + OSPF_LS_ACK_MIN_SIZE,
295 /* OSPF authentication checking function */
296 static int
297 ospf_auth_type (struct ospf_interface *oi)
298 @@ -2309,6 +2321,47 @@ ospf_check_sum (struct ospf_header *ospfh)
299 return 1;
302 +/* Verify a complete OSPF packet for proper sizing/alignment. */
303 +static unsigned
304 +ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
306 + u_int16_t bytesdeclared;
308 + /* Length, 1st approximation. */
309 + if (bytesonwire < OSPF_HEADER_SIZE)
311 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
312 + zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
313 + return MSG_NG;
315 + /* Now it is safe to access header fields. Performing length check, allow
316 + * for possible extra bytes of crypto auth/padding, which are not counted
317 + * in the OSPF header "length" field. */
318 + bytesdeclared = ntohs (oh->length);
319 + if (bytesdeclared > bytesonwire)
321 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
322 + zlog_debug ("%s: packet length error (%u real, %u declared)",
323 + __func__, bytesonwire, bytesdeclared);
324 + return MSG_NG;
326 + /* Length, 2nd approximation. The type-specific constraint is checked
327 + against declared length, not amount of bytes on wire. */
328 + if
330 + oh->type >= OSPF_MSG_HELLO &&
331 + oh->type <= OSPF_MSG_LS_ACK &&
332 + bytesdeclared < OSPF_HEADER_SIZE + ospf_packet_minlen[oh->type]
335 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
336 + zlog_debug ("%s: undersized (%u B) %s packet", __func__,
337 + bytesdeclared, LOOKUP (ospf_packet_type_str, oh->type));
338 + return MSG_NG;
340 + return MSG_OK;
343 /* OSPF Header verification. */
344 static int
345 ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
346 @@ -2404,10 +2457,10 @@ ospf_read (struct thread *thread)
347 /* prepare for next packet. */
348 ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
350 - /* read OSPF packet. */
351 stream_reset(ospf->ibuf);
352 if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))
353 return -1;
354 + /* This raw packet is known to be at least as big as its IP header. */
356 /* Note that there should not be alignment problems with this assignment
357 because this is at the beginning of the stream data buffer. */
358 @@ -2442,16 +2495,10 @@ ospf_read (struct thread *thread)
359 by ospf_recv_packet() to be correct). */
360 stream_forward_getp (ibuf, iph->ip_hl * 4);
362 - /* Make sure the OSPF header is really there. */
363 - if (stream_get_endp (ibuf) - stream_get_getp (ibuf) < OSPF_HEADER_SIZE)
365 - zlog_debug ("ospf_read: ignored OSPF packet with undersized (%u bytes) header",
366 - stream_get_endp (ibuf) - stream_get_getp (ibuf));
367 + ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
368 + if (MSG_OK != ospf_packet_examin (ospfh, stream_get_endp (ibuf) - stream_get_getp (ibuf)))
369 return -1;
372 /* Now it is safe to access all fields of OSPF packet header. */
373 - ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
375 /* associate packet with ospf interface */
376 oi = ospf_if_lookup_recv_if (ospf, iph->ip_src, ifp);
377 diff --git ospfd/ospf_packet.h ospfd/ospf_packet.h
378 index 2115f11..3cbe889 100644
379 --- ospfd/ospf_packet.h
380 +++ ospfd/ospf_packet.h
381 @@ -46,6 +46,10 @@
383 #define OSPF_HELLO_REPLY_DELAY 1
385 +/* Return values of functions involved in packet verification, see ospf6d. */
386 +#define MSG_OK 0
387 +#define MSG_NG 1
389 struct ospf_packet
391 struct ospf_packet *next;
393 cgit v0.9.0.2
394 From 3779a3bf9d27b3cccda7e45223884257af362c28 Mon Sep 17 00:00:00 2001
395 From: Denis Ovsienko <infrastation@yandex.ru>
396 Date: Mon, 30 Jan 2012 12:07:18 +0000
397 Subject: ospfd: review ospf_check_auth()
399 1. The only purpose of "ibuf" argument was to get stream size, which
400 was always equal to OSPF_MAX_PACKET_SIZE + 1, exactly as initialized
401 in ospf_new().
403 2. Fix the packet size check condition, which was incorrect for very
404 large packets, at least in theory.
406 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
407 index f425da8..a71cc99 100644
408 --- ospfd/ospf_packet.c
409 +++ ospfd/ospf_packet.c
410 @@ -2255,8 +2255,7 @@ ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
413 static int
414 -ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
415 - struct ospf_header *ospfh)
416 +ospf_check_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
418 int ret = 0;
419 struct crypt_key *ck;
420 @@ -2282,7 +2281,7 @@ ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
421 /* This is very basic, the digest processing is elsewhere */
422 if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE &&
423 ospfh->u.crypt.key_id == ck->key_id &&
424 - ntohs (ospfh->length) + OSPF_AUTH_SIMPLE_SIZE <= stream_get_size (ibuf))
425 + ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE <= OSPF_MAX_PACKET_SIZE)
426 ret = 1;
427 else
428 ret = 0;
429 @@ -2406,7 +2405,7 @@ ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
430 return -1;
433 - if (! ospf_check_auth (oi, ibuf, ospfh))
434 + if (! ospf_check_auth (oi, ospfh))
436 zlog_warn ("interface %s: ospf_read authentication failed.",
437 IF_NAME (oi));
439 cgit v0.9.0.2
440 From 7edfc01207f3eee8f26d5c22cfef7c7f030c52ce Mon Sep 17 00:00:00 2001
441 From: Denis Ovsienko <infrastation@yandex.ru>
442 Date: Mon, 30 Jan 2012 16:32:39 +0000
443 Subject: ospfd: review ospf_check_md5_digest()
445 Rewrite some pointer arithmetics without the additional variables and
446 move byte order conversion inside the function.
448 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
449 index a71cc99..5704f9d 100644
450 --- ospfd/ospf_packet.c
451 +++ ospfd/ospf_packet.c
452 @@ -304,24 +304,14 @@ ospf_packet_max (struct ospf_interface *oi)
455 static int
456 -ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
457 - u_int16_t length)
458 +ospf_check_md5_digest (struct ospf_interface *oi, struct ospf_header *ospfh)
460 - unsigned char *ibuf;
461 MD5_CTX ctx;
462 unsigned char digest[OSPF_AUTH_MD5_SIZE];
463 - unsigned char *pdigest;
464 struct crypt_key *ck;
465 - struct ospf_header *ospfh;
466 struct ospf_neighbor *nbr;
467 + u_int16_t length = ntohs (ospfh->length);
470 - ibuf = STREAM_PNT (s);
471 - ospfh = (struct ospf_header *) ibuf;
473 - /* Get pointer to the end of the packet. */
474 - pdigest = ibuf + length;
476 /* Get secret key. */
477 ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt),
478 ospfh->u.crypt.key_id);
479 @@ -347,12 +337,12 @@ ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
480 /* Generate a digest for the ospf packet - their digest + our digest. */
481 memset(&ctx, 0, sizeof(ctx));
482 MD5Init(&ctx);
483 - MD5Update(&ctx, ibuf, length);
484 + MD5Update(&ctx, ospfh, length);
485 MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE);
486 MD5Final(digest, &ctx);
488 /* compare the two */
489 - if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))
490 + if (memcmp ((caddr_t)ospfh + length, digest, OSPF_AUTH_MD5_SIZE))
492 zlog_warn ("interface %s: ospf_check_md5 checksum mismatch",
493 IF_NAME (oi));
494 @@ -2426,7 +2416,7 @@ ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
496 if (ospfh->checksum != 0)
497 return -1;
498 - if (ospf_check_md5_digest (oi, ibuf, ntohs (ospfh->length)) == 0)
499 + if (ospf_check_md5_digest (oi, ospfh) == 0)
501 zlog_warn ("interface %s: ospf_read md5 authentication failed.",
502 IF_NAME (oi));
504 cgit v0.9.0.2
505 From fba10fc38f482c617fdfbb81b8d855df56eeda51 Mon Sep 17 00:00:00 2001
506 From: Denis Ovsienko <infrastation@yandex.ru>
507 Date: Fri, 17 Feb 2012 12:20:50 +0000
508 Subject: ospfd: introduce ospf_lsa_minlen[] (BZ#705)
510 This commit ports more packet checks to OSPFv2, in particular, LSA size
511 verification and Router-LSA link blocks verification.
513 * ospf_lsa.h: add LSA size macros
514 * ospf_packet.h: add struct ospf_ls_update
515 * ospf_packet.c
516 * ospf_lsa_minlen[]: a direct equivalent of ospf6_lsa_minlen[]
517 * ospf_router_lsa_links_examin(): new function, verifies trailing
518 part of a Router-LSA
519 * ospf_lsa_examin(): new function like ospf6_lsa_examin()
520 * ospf_lsaseq_examin(): new function like ospf6_lsaseq_examin()
521 * ospf_packet_examin(): add type-specific deeper level checks
523 diff --git ospfd/ospf_lsa.h ospfd/ospf_lsa.h
524 index bf3b083..ca0653c 100644
525 --- ospfd/ospf_lsa.h
526 +++ ospfd/ospf_lsa.h
527 @@ -153,6 +153,7 @@ struct router_lsa_link
530 /* OSPF Router-LSAs structure. */
531 +#define OSPF_ROUTER_LSA_MIN_SIZE 16U /* w/1 link descriptor */
532 struct router_lsa
534 struct lsa_header header;
535 @@ -170,6 +171,7 @@ struct router_lsa
538 /* OSPF Network-LSAs structure. */
539 +#define OSPF_NETWORK_LSA_MIN_SIZE 8U /* w/1 router-ID */
540 struct network_lsa
542 struct lsa_header header;
543 @@ -178,6 +180,7 @@ struct network_lsa
546 /* OSPF Summary-LSAs structure. */
547 +#define OSPF_SUMMARY_LSA_MIN_SIZE 8U /* w/1 TOS metric block */
548 struct summary_lsa
550 struct lsa_header header;
551 @@ -187,6 +190,7 @@ struct summary_lsa
554 /* OSPF AS-external-LSAs structure. */
555 +#define OSPF_AS_EXTERNAL_LSA_MIN_SIZE 16U /* w/1 TOS forwarding block */
556 struct as_external_lsa
558 struct lsa_header header;
559 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
560 index 5704f9d..3b82820 100644
561 --- ospfd/ospf_packet.c
562 +++ ospfd/ospf_packet.c
563 @@ -73,6 +73,24 @@ static const u_int16_t ospf_packet_minlen[] =
564 OSPF_LS_ACK_MIN_SIZE,
567 +/* Minimum (besides OSPF_LSA_HEADER_SIZE) lengths for LSAs of particular
568 + types, offset is the "LSA type" field. */
569 +static const u_int16_t ospf_lsa_minlen[] =
571 + 0,
572 + OSPF_ROUTER_LSA_MIN_SIZE,
573 + OSPF_NETWORK_LSA_MIN_SIZE,
574 + OSPF_SUMMARY_LSA_MIN_SIZE,
575 + OSPF_SUMMARY_LSA_MIN_SIZE,
576 + OSPF_AS_EXTERNAL_LSA_MIN_SIZE,
577 + 0,
578 + OSPF_AS_EXTERNAL_LSA_MIN_SIZE,
579 + 0,
580 + 0,
581 + 0,
582 + 0,
585 /* OSPF authentication checking function */
586 static int
587 ospf_auth_type (struct ospf_interface *oi)
588 @@ -2310,11 +2328,199 @@ ospf_check_sum (struct ospf_header *ospfh)
589 return 1;
592 +/* Verify, that given link/TOS records are properly sized/aligned and match
593 + Router-LSA "# links" and "# TOS" fields as specified in RFC2328 A.4.2. */
594 +static unsigned
595 +ospf_router_lsa_links_examin
597 + struct router_lsa_link * link,
598 + u_int16_t linkbytes,
599 + const u_int16_t num_links
602 + unsigned counted_links = 0, thislinklen;
604 + while (linkbytes)
606 + thislinklen = OSPF_ROUTER_LSA_LINK_SIZE + 4 * link->m[0].tos_count;
607 + if (thislinklen > linkbytes)
609 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
610 + zlog_debug ("%s: length error in link block #%u", __func__, counted_links);
611 + return MSG_NG;
613 + link = (struct router_lsa_link *)((caddr_t) link + thislinklen);
614 + linkbytes -= thislinklen;
615 + counted_links++;
617 + if (counted_links != num_links)
619 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
620 + zlog_debug ("%s: %u link blocks declared, %u present",
621 + __func__, num_links, counted_links);
622 + return MSG_NG;
624 + return MSG_OK;
627 +/* Verify, that the given LSA is properly sized/aligned (including type-specific
628 + minimum length constraint). */
629 +static unsigned
630 +ospf_lsa_examin (struct lsa_header * lsah, const u_int16_t lsalen, const u_char headeronly)
632 + unsigned ret;
633 + struct router_lsa * rlsa;
634 + if
636 + lsah->type < OSPF_MAX_LSA &&
637 + ospf_lsa_minlen[lsah->type] &&
638 + lsalen < OSPF_LSA_HEADER_SIZE + ospf_lsa_minlen[lsah->type]
641 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
642 + zlog_debug ("%s: undersized (%u B) %s",
643 + __func__, lsalen, LOOKUP (ospf_lsa_type_msg, lsah->type));
644 + return MSG_NG;
646 + switch (lsah->type)
648 + case OSPF_ROUTER_LSA:
649 + /* RFC2328 A.4.2, LSA header + 4 bytes followed by N>=1 (12+)-byte link blocks */
650 + if (headeronly)
652 + ret = (lsalen - OSPF_LSA_HEADER_SIZE - OSPF_ROUTER_LSA_MIN_SIZE) % 4 ? MSG_NG : MSG_OK;
653 + break;
655 + rlsa = (struct router_lsa *) lsah;
656 + ret = ospf_router_lsa_links_examin
658 + (struct router_lsa_link *) rlsa->link,
659 + lsalen - OSPF_LSA_HEADER_SIZE - 4, /* skip: basic header, "flags", 0, "# links" */
660 + ntohs (rlsa->links) /* 16 bits */
661 + );
662 + break;
663 + case OSPF_AS_EXTERNAL_LSA:
664 + /* RFC2328 A.4.5, LSA header + 4 bytes followed by N>=1 12-bytes long blocks */
665 + case OSPF_AS_NSSA_LSA:
666 + /* RFC3101 C, idem */
667 + ret = (lsalen - OSPF_LSA_HEADER_SIZE - OSPF_AS_EXTERNAL_LSA_MIN_SIZE) % 12 ? MSG_NG : MSG_OK;
668 + break;
669 + /* Following LSA types are considered OK length-wise as soon as their minimum
670 + * length constraint is met and length of the whole LSA is a multiple of 4
671 + * (basic LSA header size is already a multiple of 4). */
672 + case OSPF_NETWORK_LSA:
673 + /* RFC2328 A.4.3, LSA header + 4 bytes followed by N>=1 router-IDs */
674 + case OSPF_SUMMARY_LSA:
675 + case OSPF_ASBR_SUMMARY_LSA:
676 + /* RFC2328 A.4.4, LSA header + 4 bytes followed by N>=1 4-bytes TOS blocks */
677 +#ifdef HAVE_OPAQUE_LSA
678 + case OSPF_OPAQUE_LINK_LSA:
679 + case OSPF_OPAQUE_AREA_LSA:
680 + case OSPF_OPAQUE_AS_LSA:
681 + /* RFC5250 A.2, "some number of octets (of application-specific
682 + * data) padded to 32-bit alignment." This is considered equivalent
683 + * to 4-byte alignment of all other LSA types, see OSPF-ALIGNMENT.txt
684 + * file for the detailed analysis of this passage. */
685 +#endif
686 + ret = lsalen % 4 ? MSG_NG : MSG_OK;
687 + break;
688 + default:
689 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
690 + zlog_debug ("%s: unsupported LSA type 0x%02x", __func__, lsah->type);
691 + return MSG_NG;
693 + if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET (0, RECV))
694 + zlog_debug ("%s: alignment error in %s",
695 + __func__, LOOKUP (ospf_lsa_type_msg, lsah->type));
696 + return ret;
699 +/* Verify if the provided input buffer is a valid sequence of LSAs. This
700 + includes verification of LSA blocks length/alignment and dispatching
701 + of deeper-level checks. */
702 +static unsigned
703 +ospf_lsaseq_examin
705 + struct lsa_header *lsah, /* start of buffered data */
706 + size_t length,
707 + const u_char headeronly,
708 + /* When declared_num_lsas is not 0, compare it to the real number of LSAs
709 + and treat the difference as an error. */
710 + const u_int32_t declared_num_lsas
713 + u_int32_t counted_lsas = 0;
715 + while (length)
717 + u_int16_t lsalen;
718 + if (length < OSPF_LSA_HEADER_SIZE)
720 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
721 + zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header",
722 + __func__, length, counted_lsas);
723 + return MSG_NG;
725 + /* save on ntohs() calls here and in the LSA validator */
726 + lsalen = ntohs (lsah->length);
727 + if (lsalen < OSPF_LSA_HEADER_SIZE)
729 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
730 + zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
731 + __func__, counted_lsas, lsalen);
732 + return MSG_NG;
734 + if (headeronly)
736 + /* less checks here and in ospf_lsa_examin() */
737 + if (MSG_OK != ospf_lsa_examin (lsah, lsalen, 1))
739 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
740 + zlog_debug ("%s: malformed header-only LSA #%u", __func__, counted_lsas);
741 + return MSG_NG;
743 + lsah = (struct lsa_header *) ((caddr_t) lsah + OSPF_LSA_HEADER_SIZE);
744 + length -= OSPF_LSA_HEADER_SIZE;
746 + else
748 + /* make sure the input buffer is deep enough before further checks */
749 + if (lsalen > length)
751 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
752 + zlog_debug ("%s: anomaly in LSA #%u: declared length is %u B, buffered length is %zu B",
753 + __func__, counted_lsas, lsalen, length);
754 + return MSG_NG;
756 + if (MSG_OK != ospf_lsa_examin (lsah, lsalen, 0))
758 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
759 + zlog_debug ("%s: malformed LSA #%u", __func__, counted_lsas);
760 + return MSG_NG;
762 + lsah = (struct lsa_header *) ((caddr_t) lsah + lsalen);
763 + length -= lsalen;
765 + counted_lsas++;
768 + if (declared_num_lsas && counted_lsas != declared_num_lsas)
770 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
771 + zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
772 + __func__, declared_num_lsas, counted_lsas);
773 + return MSG_NG;
775 + return MSG_OK;
778 /* Verify a complete OSPF packet for proper sizing/alignment. */
779 static unsigned
780 ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
782 u_int16_t bytesdeclared;
783 + unsigned ret;
784 + struct ospf_ls_update * lsupd;
786 /* Length, 1st approximation. */
787 if (bytesonwire < OSPF_HEADER_SIZE)
788 @@ -2348,7 +2554,59 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
789 bytesdeclared, LOOKUP (ospf_packet_type_str, oh->type));
790 return MSG_NG;
792 - return MSG_OK;
793 + switch (oh->type)
795 + case OSPF_MSG_HELLO:
796 + /* RFC2328 A.3.2, packet header + OSPF_HELLO_MIN_SIZE bytes followed
797 + by N>=0 router-IDs. */
798 + ret = (bytesonwire - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE) % 4 ? MSG_NG : MSG_OK;
799 + break;
800 + case OSPF_MSG_DB_DESC:
801 + /* RFC2328 A.3.3, packet header + OSPF_DB_DESC_MIN_SIZE bytes followed
802 + by N>=0 header-only LSAs. */
803 + ret = ospf_lsaseq_examin
805 + (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_DB_DESC_MIN_SIZE),
806 + bytesonwire - OSPF_HEADER_SIZE - OSPF_DB_DESC_MIN_SIZE,
807 + 1, /* header-only LSAs */
809 + );
810 + break;
811 + case OSPF_MSG_LS_REQ:
812 + /* RFC2328 A.3.4, packet header followed by N>=0 12-bytes request blocks. */
813 + ret = (bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_REQ_MIN_SIZE) %
814 + OSPF_LSA_KEY_SIZE ? MSG_NG : MSG_OK;
815 + break;
816 + case OSPF_MSG_LS_UPD:
817 + /* RFC2328 A.3.5, packet header + OSPF_LS_UPD_MIN_SIZE bytes followed
818 + by N>=0 full LSAs (with N declared beforehand). */
819 + lsupd = (struct ospf_ls_update *) ((caddr_t) oh + OSPF_HEADER_SIZE);
820 + ret = ospf_lsaseq_examin
822 + (struct lsa_header *) ((caddr_t) lsupd + OSPF_LS_UPD_MIN_SIZE),
823 + bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_UPD_MIN_SIZE,
824 + 0, /* full LSAs */
825 + ntohl (lsupd->num_lsas) /* 32 bits */
826 + );
827 + break;
828 + case OSPF_MSG_LS_ACK:
829 + /* RFC2328 A.3.6, packet header followed by N>=0 header-only LSAs. */
830 + ret = ospf_lsaseq_examin
832 + (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_LS_ACK_MIN_SIZE),
833 + bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_ACK_MIN_SIZE,
834 + 1, /* header-only LSAs */
836 + );
837 + break;
838 + default:
839 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
840 + zlog_debug ("%s: invalid packet type 0x%02x", __func__, oh->type);
841 + return MSG_NG;
843 + if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET (0, RECV))
844 + zlog_debug ("%s: malformed %s packet", __func__, LOOKUP (ospf_packet_type_str, oh->type));
845 + return ret;
848 /* OSPF Header verification. */
849 diff --git ospfd/ospf_packet.h ospfd/ospf_packet.h
850 index 3cbe889..337686a 100644
851 --- ospfd/ospf_packet.h
852 +++ ospfd/ospf_packet.h
853 @@ -121,6 +121,10 @@ struct ospf_db_desc
854 u_int32_t dd_seqnum;
857 +struct ospf_ls_update
859 + u_int32_t num_lsas;
862 /* Macros. */
863 /* XXX Perhaps obsolete; function in ospf_packet.c */
865 cgit v0.9.0.2
866 From b03ae9f2d22acd8e3f97714a9c0df744676e344d Mon Sep 17 00:00:00 2001
867 From: Denis Ovsienko <infrastation@yandex.ru>
868 Date: Mon, 20 Feb 2012 19:08:10 +0000
869 Subject: ospfd: fix packet length check for auth/LLS cases
871 An OSPFv2 packet with trailing data blocks (authentication and/or
872 link-local signaling) failed the recently implemented packet length
873 check, because trailing data length isn't counted in the packet header
874 "length" field. This commit fixes respective check conditions.
876 * ospf_packet.c
877 * ospf_packet_examin(): use "bytesdeclared" instead of "bytesonwire"
879 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
880 index 3b82820..7b661a3 100644
881 --- ospfd/ospf_packet.c
882 +++ ospfd/ospf_packet.c
883 @@ -2559,7 +2559,7 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
884 case OSPF_MSG_HELLO:
885 /* RFC2328 A.3.2, packet header + OSPF_HELLO_MIN_SIZE bytes followed
886 by N>=0 router-IDs. */
887 - ret = (bytesonwire - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE) % 4 ? MSG_NG : MSG_OK;
888 + ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE) % 4 ? MSG_NG : MSG_OK;
889 break;
890 case OSPF_MSG_DB_DESC:
891 /* RFC2328 A.3.3, packet header + OSPF_DB_DESC_MIN_SIZE bytes followed
892 @@ -2567,14 +2567,14 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
893 ret = ospf_lsaseq_examin
895 (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_DB_DESC_MIN_SIZE),
896 - bytesonwire - OSPF_HEADER_SIZE - OSPF_DB_DESC_MIN_SIZE,
897 + bytesdeclared - OSPF_HEADER_SIZE - OSPF_DB_DESC_MIN_SIZE,
898 1, /* header-only LSAs */
901 break;
902 case OSPF_MSG_LS_REQ:
903 /* RFC2328 A.3.4, packet header followed by N>=0 12-bytes request blocks. */
904 - ret = (bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_REQ_MIN_SIZE) %
905 + ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_REQ_MIN_SIZE) %
906 OSPF_LSA_KEY_SIZE ? MSG_NG : MSG_OK;
907 break;
908 case OSPF_MSG_LS_UPD:
909 @@ -2584,7 +2584,7 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
910 ret = ospf_lsaseq_examin
912 (struct lsa_header *) ((caddr_t) lsupd + OSPF_LS_UPD_MIN_SIZE),
913 - bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_UPD_MIN_SIZE,
914 + bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_UPD_MIN_SIZE,
915 0, /* full LSAs */
916 ntohl (lsupd->num_lsas) /* 32 bits */
918 @@ -2594,7 +2594,7 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
919 ret = ospf_lsaseq_examin
921 (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_LS_ACK_MIN_SIZE),
922 - bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_ACK_MIN_SIZE,
923 + bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_ACK_MIN_SIZE,
924 1, /* header-only LSAs */
928 cgit v0.9.0.2
929 From 1bdd96caefaa76883bece4d358a60dc890f1e375 Mon Sep 17 00:00:00 2001
930 From: Denis Ovsienko <infrastation@yandex.ru>
931 Date: Sun, 26 Feb 2012 13:00:57 +0000
932 Subject: ospfd: introduce ospf_auth_type_str[]
935 diff --git ospfd/ospf_dump.c ospfd/ospf_dump.c
936 index 8ace095..7e11e25 100644
937 --- ospfd/ospf_dump.c
938 +++ ospfd/ospf_dump.c
939 @@ -115,6 +115,16 @@ const struct message ospf_network_type_msg[] =
941 const int ospf_network_type_msg_max = OSPF_IFTYPE_MAX;
943 +/* AuType */
944 +const struct message ospf_auth_type_str[] =
946 + { OSPF_AUTH_NULL, "Null" },
947 + { OSPF_AUTH_SIMPLE, "Simple" },
948 + { OSPF_AUTH_CRYPTOGRAPHIC, "Cryptographic" },
950 +const size_t ospf_auth_type_str_max = sizeof (ospf_auth_type_str) /
951 + sizeof (ospf_auth_type_str[0]);
953 /* Configuration debug option variables. */
954 unsigned long conf_debug_ospf_packet[5] = {0, 0, 0, 0, 0};
955 unsigned long conf_debug_ospf_event = 0;
956 @@ -657,6 +667,7 @@ static void
957 ospf_header_dump (struct ospf_header *ospfh)
959 char buf[9];
960 + u_int16_t auth_type = ntohs (ospfh->auth_type);
962 zlog_debug ("Header");
963 zlog_debug (" Version %d", ospfh->version);
964 @@ -666,9 +677,9 @@ ospf_header_dump (struct ospf_header *ospfh)
965 zlog_debug (" Router ID %s", inet_ntoa (ospfh->router_id));
966 zlog_debug (" Area ID %s", inet_ntoa (ospfh->area_id));
967 zlog_debug (" Checksum 0x%x", ntohs (ospfh->checksum));
968 - zlog_debug (" AuType %d", ntohs (ospfh->auth_type));
969 + zlog_debug (" AuType %s", LOOKUP (ospf_auth_type_str, auth_type));
971 - switch (ntohs (ospfh->auth_type))
972 + switch (auth_type)
974 case OSPF_AUTH_NULL:
975 break;
976 diff --git ospfd/ospf_dump.h ospfd/ospf_dump.h
977 index 455214f..a2d5e8b 100644
978 --- ospfd/ospf_dump.h
979 +++ ospfd/ospf_dump.h
980 @@ -122,6 +122,8 @@ extern unsigned long term_debug_ospf_nssa;
982 /* Message Strings. */
983 extern char *ospf_lsa_type_str[];
984 +extern const struct message ospf_auth_type_str[];
985 +extern const size_t ospf_auth_type_str_max;
987 /* Prototypes. */
988 extern const char *ospf_area_name_string (struct ospf_area *);
990 cgit v0.9.0.2
991 From e5fa148725fb2a3d1a8df12683f023ff9d65273f Mon Sep 17 00:00:00 2001
992 From: Denis Ovsienko <infrastation@yandex.ru>
993 Date: Sun, 26 Feb 2012 13:59:43 +0000
994 Subject: ospfd: bring ospf_check_auth() into focus
996 The old ospf_check_auth() function did two different jobs depending on
997 AuType. For Null and Simple cases it actually authenticated the packet,
998 but for Cryptographic case it only checked declared packet size (not
999 taking the actual number of bytes on wire into account). The calling
1000 function, ospf_verify_header(), had its own set of MD5/checksum checks
1001 dispatched depending on AuType.
1003 This commit makes the packet size check work against the real number of
1004 bytes and moves it to ospf_packet_examine(). All MD5/checksum
1005 verification is now performed in ospf_check_auth() function.
1007 * ospf_packet.c
1008 * ospf_packet_examin(): check length with MD5 bytes in mind
1009 * ospf_verify_header(): remove all AuType-specific code
1010 * ospf_check_auth(): completely rewrite
1012 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
1013 index 7b661a3..05651d3 100644
1014 --- ospfd/ospf_packet.c
1015 +++ ospfd/ospf_packet.c
1016 @@ -91,6 +91,9 @@ static const u_int16_t ospf_lsa_minlen[] =
1020 +/* for ospf_check_auth() */
1021 +static int ospf_check_sum (struct ospf_header *);
1023 /* OSPF authentication checking function */
1024 static int
1025 ospf_auth_type (struct ospf_interface *oi)
1026 @@ -2262,44 +2265,91 @@ ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
1027 return 0;
1030 +/* Return 1, if the packet is properly authenticated and checksummed,
1031 + 0 otherwise. In particular, check that AuType header field is valid and
1032 + matches the locally configured AuType, and that D.5 requirements are met. */
1033 static int
1034 ospf_check_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
1036 - int ret = 0;
1037 struct crypt_key *ck;
1038 + u_int16_t iface_auth_type;
1039 + u_int16_t pkt_auth_type = ntohs (ospfh->auth_type);
1041 - switch (ntohs (ospfh->auth_type))
1042 + switch (pkt_auth_type)
1044 + case OSPF_AUTH_NULL: /* RFC2328 D.5.1 */
1045 + if (OSPF_AUTH_NULL != (iface_auth_type = ospf_auth_type (oi)))
1047 - case OSPF_AUTH_NULL:
1048 - ret = 1;
1049 - break;
1050 - case OSPF_AUTH_SIMPLE:
1051 - if (!memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))
1052 - ret = 1;
1053 - else
1054 - ret = 0;
1055 - break;
1056 - case OSPF_AUTH_CRYPTOGRAPHIC:
1057 - if ((ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) == NULL)
1059 - ret = 0;
1060 - break;
1063 - /* This is very basic, the digest processing is elsewhere */
1064 - if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE &&
1065 - ospfh->u.crypt.key_id == ck->key_id &&
1066 - ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE <= OSPF_MAX_PACKET_SIZE)
1067 - ret = 1;
1068 - else
1069 - ret = 0;
1070 - break;
1071 - default:
1072 - ret = 0;
1073 - break;
1074 + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
1075 + zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Null",
1076 + IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type));
1077 + return 0;
1080 - return ret;
1081 + if (! ospf_check_sum (ospfh))
1083 + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
1084 + zlog_warn ("interface %s: Null auth OK, but checksum error, Router-ID %s",
1085 + IF_NAME (oi), inet_ntoa (ospfh->router_id));
1086 + return 0;
1088 + return 1;
1089 + case OSPF_AUTH_SIMPLE: /* RFC2328 D.5.2 */
1090 + if (OSPF_AUTH_SIMPLE != (iface_auth_type = ospf_auth_type (oi)))
1092 + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
1093 + zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Simple",
1094 + IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type));
1095 + return 0;
1097 + if (memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))
1099 + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
1100 + zlog_warn ("interface %s: Simple auth failed", IF_NAME (oi));
1101 + return 0;
1103 + if (! ospf_check_sum (ospfh))
1105 + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
1106 + zlog_warn ("interface %s: Simple auth OK, checksum error, Router-ID %s",
1107 + IF_NAME (oi), inet_ntoa (ospfh->router_id));
1108 + return 0;
1110 + return 1;
1111 + case OSPF_AUTH_CRYPTOGRAPHIC: /* RFC2328 D.5.3 */
1112 + if (OSPF_AUTH_CRYPTOGRAPHIC != (iface_auth_type = ospf_auth_type (oi)))
1114 + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
1115 + zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Cryptographic",
1116 + IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type));
1117 + return 0;
1119 + if (ospfh->checksum)
1121 + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
1122 + zlog_warn ("interface %s: OSPF header checksum is not 0", IF_NAME (oi));
1123 + return 0;
1125 + /* only MD5 crypto method can pass ospf_packet_examin() */
1126 + if
1128 + NULL == (ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) ||
1129 + ospfh->u.crypt.key_id != ck->key_id ||
1130 + /* Condition above uses the last key ID on the list, which is
1131 + different from what ospf_crypt_key_lookup() does. A bug? */
1132 + ! ospf_check_md5_digest (oi, ospfh)
1135 + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
1136 + zlog_warn ("interface %s: MD5 auth failed", IF_NAME (oi));
1137 + return 0;
1139 + return 1;
1140 + default:
1141 + if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
1142 + zlog_warn ("interface %s: invalid packet auth-type (%02x)",
1143 + IF_NAME (oi), pkt_auth_type);
1144 + return 0;
1148 static int
1149 @@ -2518,7 +2568,7 @@ ospf_lsaseq_examin
1150 static unsigned
1151 ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
1153 - u_int16_t bytesdeclared;
1154 + u_int16_t bytesdeclared, bytesauth;
1155 unsigned ret;
1156 struct ospf_ls_update * lsupd;
1158 @@ -2533,11 +2583,24 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
1159 * for possible extra bytes of crypto auth/padding, which are not counted
1160 * in the OSPF header "length" field. */
1161 bytesdeclared = ntohs (oh->length);
1162 - if (bytesdeclared > bytesonwire)
1163 + if (ntohs (oh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
1164 + bytesauth = 0;
1165 + else
1167 + if (oh->u.crypt.auth_data_len != OSPF_AUTH_MD5_SIZE)
1169 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
1170 + zlog_debug ("%s: unsupported crypto auth length (%u B)",
1171 + __func__, oh->u.crypt.auth_data_len);
1172 + return MSG_NG;
1174 + bytesauth = OSPF_AUTH_MD5_SIZE;
1176 + if (bytesdeclared + bytesauth > bytesonwire)
1178 if (IS_DEBUG_OSPF_PACKET (0, RECV))
1179 - zlog_debug ("%s: packet length error (%u real, %u declared)",
1180 - __func__, bytesonwire, bytesdeclared);
1181 + zlog_debug ("%s: packet length error (%u real, %u+%u declared)",
1182 + __func__, bytesonwire, bytesdeclared, bytesauth);
1183 return MSG_NG;
1185 /* Length, 2nd approximation. The type-specific constraint is checked
1186 @@ -2645,42 +2708,9 @@ ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
1187 return -1;
1190 - /* Check authentication. */
1191 - if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
1193 - zlog_warn ("interface %s: auth-type mismatch, local %d, rcvd %d",
1194 - IF_NAME (oi), ospf_auth_type (oi), ntohs (ospfh->auth_type));
1195 - return -1;
1198 + /* Check authentication. The function handles logging actions, where required. */
1199 if (! ospf_check_auth (oi, ospfh))
1201 - zlog_warn ("interface %s: ospf_read authentication failed.",
1202 - IF_NAME (oi));
1203 - return -1;
1206 - /* if check sum is invalid, packet is discarded. */
1207 - if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
1209 - if (! ospf_check_sum (ospfh))
1211 - zlog_warn ("interface %s: ospf_read packet checksum error %s",
1212 - IF_NAME (oi), inet_ntoa (ospfh->router_id));
1213 - return -1;
1216 - else
1218 - if (ospfh->checksum != 0)
1219 - return -1;
1220 - if (ospf_check_md5_digest (oi, ospfh) == 0)
1222 - zlog_warn ("interface %s: ospf_read md5 authentication failed.",
1223 - IF_NAME (oi));
1224 - return -1;
1227 + return -1;
1229 return 0;
1232 cgit v0.9.0.2
1233 From a59c5401a2df169de2c780f13a4563548c04a2b7 Mon Sep 17 00:00:00 2001
1234 From: Denis Ovsienko <infrastation@yandex.ru>
1235 Date: Tue, 28 Feb 2012 11:15:29 +0000
1236 Subject: ospfd: reduce ospf_verify_header()
1238 Protocol version checks fits ospf_packet_examin() better (like it is
1239 implemented in ospf6d), and packet type check is already there.
1241 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
1242 index 05651d3..de14ccc 100644
1243 --- ospfd/ospf_packet.c
1244 +++ ospfd/ospf_packet.c
1245 @@ -2582,6 +2582,12 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
1246 /* Now it is safe to access header fields. Performing length check, allow
1247 * for possible extra bytes of crypto auth/padding, which are not counted
1248 * in the OSPF header "length" field. */
1249 + if (oh->version != OSPF_VERSION)
1251 + if (IS_DEBUG_OSPF_PACKET (0, RECV))
1252 + zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
1253 + return MSG_NG;
1255 bytesdeclared = ntohs (oh->length);
1256 if (ntohs (oh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
1257 bytesauth = 0;
1258 @@ -2677,21 +2683,6 @@ static int
1259 ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
1260 struct ip *iph, struct ospf_header *ospfh)
1262 - /* check version. */
1263 - if (ospfh->version != OSPF_VERSION)
1265 - zlog_warn ("interface %s: ospf_read version number mismatch.",
1266 - IF_NAME (oi));
1267 - return -1;
1270 - /* Valid OSPFv2 packet types are 1 through 5 inclusive. */
1271 - if (ospfh->type < 1 || ospfh->type > 5)
1273 - zlog_warn ("interface %s: invalid packet type %u", IF_NAME (oi), ospfh->type);
1274 - return -1;
1277 /* Check Area ID. */
1278 if (!ospf_check_area_id (oi, ospfh))
1281 cgit v0.9.0.2