1: /*
2: * BIRD -- OSPF
3: *
4: * (c) 1999--2005 Ondrej Filip <feela@network.cz>
5: * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
6: * (c) 2009--2014 CZ.NIC z.s.p.o.
7: *
8: * Can be freely distributed and used under the terms of the GNU GPL.
9: */
10:
11: #include "ospf.h"
12: #include "nest/password.h"
13: #include "lib/md5.h"
14: #include "lib/mac.h"
15: #include "lib/socket.h"
16:
17: void
18: ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
19: {
20: struct ospf_proto *p = ifa->oa->po;
21: struct ospf_packet *pkt;
22:
23: pkt = (struct ospf_packet *) buf;
24:
25: pkt->version = ospf_get_version(p);
26: pkt->type = h_type;
27: pkt->length = htons(ospf_pkt_maxsize(ifa));
28: pkt->routerid = htonl(p->router_id);
29: pkt->areaid = htonl(ifa->oa->areaid);
30: pkt->checksum = 0;
31: pkt->instance_id = ifa->instance_id;
32: pkt->autype = ospf_is_v2(p) ? ifa->autype : 0;
33: }
34:
35: /* We assume OSPFv2 in ospf_pkt_finalize() */
36: static void
37: ospf_pkt_finalize2(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
38: {
39: struct ospf_proto *p = ifa->oa->po;
40: struct password_item *pass = NULL;
41: union ospf_auth2 *auth = (void *) (pkt + 1);
42: memset(auth, 0, sizeof(union ospf_auth2));
43:
44: /* Compatibility note: auth may contain anything if autype is
45: none, but nonzero values do not work with Mikrotik OSPF */
46:
47: pkt->checksum = 0;
48: pkt->autype = ifa->autype;
49:
50: switch (ifa->autype)
51: {
52: case OSPF_AUTH_SIMPLE:
53: pass = password_find(ifa->passwords, 1);
54: if (!pass)
55: {
56: log(L_ERR "No suitable password found for authentication");
57: return;
58: }
59: strncpy(auth->password, pass->password, sizeof(auth->password));
60: /* fallthrough */
61:
62: case OSPF_AUTH_NONE:
63: {
64: void *body = (void *) (auth + 1);
65: uint blen = *plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth2);
66: pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL);
67: }
68: break;
69:
70: case OSPF_AUTH_CRYPT:
71: pass = password_find(ifa->passwords, 0);
72: if (!pass)
73: {
74: log(L_ERR "%s: No suitable password found for authentication", p->p.name);
75: return;
76: }
77:
78: /* Perhaps use random value to prevent replay attacks after
79: reboot when system does not have independent RTC? */
80: if (!ifa->csn)
81: {
82: ifa->csn = (u32) (current_real_time() TO_S);
83: ifa->csn_use = current_time();
84: }
85:
86: /* We must have sufficient delay between sending a packet and increasing
87: CSN to prevent reordering of packets (in a network) with different CSNs */
88: if ((current_time() - ifa->csn_use) > 1 S)
89: ifa->csn++;
90:
91: ifa->csn_use = current_time();
92:
93: uint auth_len = mac_type_length(pass->alg);
94: byte *auth_tail = ((byte *) pkt + *plen);
95: *plen += auth_len;
96:
97: ASSERT(*plen < ifa->sk->tbsize);
98:
99: auth->c32.zero = 0;
100: auth->c32.keyid = pass->id;
101: auth->c32.len = auth_len;
102: auth->c32.csn = htonl(ifa->csn);
103:
104: /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
105: if (pass->alg < ALG_HMAC)
106: strncpy(auth_tail, pass->password, auth_len);
107: else
108: memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
109:
110: mac_fill(pass->alg, pass->password, pass->length, (byte *) pkt, *plen, auth_tail);
111: break;
112:
113: default:
114: bug("Unknown authentication type");
115: }
116: }
117:
118: /*
119: * Return an extra packet size that should be added to a final packet size
120: */
121: static void
122: ospf_pkt_finalize3(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen, ip_addr src)
123: {
124: struct ospf_proto *p = ifa->oa->po;
125: struct ospf_auth3 *auth = (void *) ((byte *) pkt + *plen);
126:
127: pkt->checksum = 0;
128: pkt->autype = 0;
129:
130: if (ifa->autype != OSPF_AUTH_CRYPT)
131: return;
132:
133: struct password_item *pass = password_find(ifa->passwords, 0);
134: if (!pass)
135: {
136: log(L_ERR "%s: No suitable password found for authentication", p->p.name);
137: return;
138: }
139:
140: /* FIXME: Ensure persistence */
141: p->csn64++;
142:
143: uint mac_len = mac_type_length(pass->alg);
144: uint auth_len = sizeof(struct ospf_auth3) + mac_len;
145: *plen += auth_len;
146:
147: ASSERT(*plen < ifa->sk->tbsize);
148:
149: memset(auth, 0, sizeof(struct ospf_auth3));
150: auth->type = htons(OSPF3_AUTH_HMAC);
151: auth->length = htons(auth_len);
152: auth->reserved = 0;
153: auth->sa_id = htons(pass->id);
154: put_u64(&auth->csn, p->csn64);
155:
156: /* Initialize with src IP address padded with HMAC_MAGIC */
157: put_ip6(auth->data, ipa_to_ip6(src));
158: memset32(auth->data + 16, HMAC_MAGIC, (mac_len - 16) / 4);
159:
160: /* Attach OSPFv3 Cryptographic Protocol ID to the key */
161: uint pass_len = pass->length + 2;
162: byte *pass_key = alloca(pass_len);
163: memcpy(pass_key, pass->password, pass->length);
164: put_u16(pass_key + pass->length, OSPF3_CRYPTO_ID);
165:
166: mac_fill(pass->alg, pass_key, pass_len, (byte *) pkt, *plen, auth->data);
167: }
168:
169:
170: static int
171: ospf_pkt_checkauth2(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len)
172: {
173: struct ospf_proto *p = ifa->oa->po;
174: union ospf_auth2 *auth = (void *) (pkt + 1);
175: struct password_item *pass = NULL;
176: const char *err_dsc = NULL;
177: uint err_val = 0;
178:
179: uint plen = ntohs(pkt->length);
180: u8 autype = pkt->autype;
181:
182: if (autype != ifa->autype)
183: DROP("authentication method mismatch", autype);
184:
185: switch (autype)
186: {
187: case OSPF_AUTH_NONE:
188: return 1;
189:
190: case OSPF_AUTH_SIMPLE:
191: pass = password_find(ifa->passwords, 1);
192: if (!pass)
193: DROP1("no password found");
194:
195: if (!password_verify(pass, auth->password, sizeof(auth->password)))
196: DROP("wrong password", pass->id);
197:
198: return 1;
199:
200: case OSPF_AUTH_CRYPT:
201: pass = password_find_by_id(ifa->passwords, auth->c32.keyid);
202: if (!pass)
203: DROP("no suitable password found", auth->c32.keyid);
204:
205: uint auth_len = mac_type_length(pass->alg);
206:
207: if (plen + auth->c32.len > len)
208: DROP("packet length mismatch", len);
209:
210: if (auth->c32.len != auth_len)
211: DROP("wrong authentication length", auth->c32.len);
212:
213: u32 rcv_csn = ntohl(auth->c32.csn);
214: if (n && (rcv_csn < n->csn))
215: // DROP("lower sequence number", rcv_csn);
216: {
217: /* We want to report both new and old CSN */
218: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
219: "lower sequence number (rcv %u, old %u)",
220: n->rid, ifa->ifname, rcv_csn, n->csn);
221: return 0;
222: }
223:
224: byte *auth_tail = ((byte *) pkt) + plen;
225: byte *auth_data = alloca(auth_len);
226: memcpy(auth_data, auth_tail, auth_len);
227:
228: /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */
229: if (pass->alg < ALG_HMAC)
230: strncpy(auth_tail, pass->password, auth_len);
231: else
232: memset32(auth_tail, HMAC_MAGIC, auth_len / 4);
233:
234: if (!mac_verify(pass->alg, pass->password, pass->length,
235: (byte *) pkt, plen + auth_len, auth_data))
236: DROP("wrong authentication code", pass->id);
237:
238: if (n)
239: n->csn = rcv_csn;
240:
241: return 1;
242:
243: default:
244: bug("Unknown authentication type");
245: }
246:
247: drop:
248: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)",
249: (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val);
250:
251: return 0;
252: }
253:
254: static int
255: ospf_pkt_checkauth3(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len, ip_addr src)
256: {
257: struct ospf_proto *p = ifa->oa->po;
258: const char *err_dsc = NULL;
259: uint err_val = 0;
260:
261: uint plen = ntohs(pkt->length);
262: uint opts, lls_present, auth_present;
263:
264: /*
265: * When autentication is not enabled, ignore the trailer. This is different
266: * from OSPFv2, but it is necessary in order to support migration modes. Note
267: * that regular authenticated packets do not have valid checksum and will be
268: * dropped by OS on non-authenticated ifaces.
269: */
270: if (ifa->autype != OSPF_AUTH_CRYPT)
271: return 1;
272:
273: switch(pkt->type)
274: {
275: case HELLO_P:
276: opts = ospf_hello3_options(pkt);
277: lls_present = opts & OPT_L_V3;
278: auth_present = opts & OPT_AT;
279: break;
280:
281: case DBDES_P:
282: opts = ospf_dbdes3_options(pkt);
283: lls_present = opts & OPT_L_V3;
284: auth_present = opts & OPT_AT;
285: break;
286:
287: default:
288: lls_present = 0;
289: auth_present = n->options & OPT_AT;
290: }
291:
292: if (!auth_present)
293: DROP1("missing authentication trailer");
294:
295: if (lls_present)
296: {
297: if ((plen + sizeof(struct ospf_lls)) > len)
298: DROP("packet length mismatch", len);
299:
300: struct ospf_lls *lls = (void *) ((byte *) pkt + plen);
301: plen += ntohs(lls->length);
302: }
303:
304: if ((plen + sizeof(struct ospf_auth3)) > len)
305: DROP("packet length mismatch", len);
306:
307: struct ospf_auth3 *auth = (void *) ((byte *) pkt + plen);
308:
309: uint rcv_auth_type = ntohs(auth->type);
310: if (rcv_auth_type != OSPF3_AUTH_HMAC)
311: DROP("authentication method mismatch", rcv_auth_type);
312:
313: uint rcv_auth_len = ntohs(auth->length);
314: if (plen + rcv_auth_len > len)
315: DROP("packet length mismatch", len);
316:
317: uint rcv_key_id = ntohs(auth->sa_id);
318: struct password_item *pass = password_find_by_id(ifa->passwords, rcv_key_id);
319: if (!pass)
320: DROP("no suitable password found", rcv_key_id);
321:
322: uint mac_len = mac_type_length(pass->alg);
323: if (rcv_auth_len != (sizeof(struct ospf_auth3) + mac_len))
324: DROP("wrong authentication length", rcv_auth_len);
325:
326: uint pt = pkt->type - 1;
327: u64 rcv_csn = get_u64(&auth->csn);
328: if (n && (rcv_csn <= n->csn64[pt]))
329: {
330: /* We want to report both new and old CSN */
331: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
332: "lower sequence number (rcv %u, old %u)",
333: n->rid, ifa->ifname, (uint) rcv_csn, (uint) n->csn64[pt]);
334: return 0;
335: }
336:
337: /* Save the received authentication data */
338: byte *auth_data = alloca(mac_len);
339: memcpy(auth_data, auth->data, mac_len);
340:
341: /* Initialize with src IP address padded with HMAC_MAGIC */
342: put_ip6(auth->data, ipa_to_ip6(src));
343: memset32(auth->data + 16, HMAC_MAGIC, (mac_len - 16) / 4);
344:
345: /* Attach OSPFv3 Cryptographic Protocol ID to the key */
346: uint pass_len = pass->length + 2;
347: byte *pass_key = alloca(pass_len);
348: memcpy(pass_key, pass->password, pass->length);
349: put_u16(pass_key + pass->length, OSPF3_CRYPTO_ID);
350:
351: if (!mac_verify(pass->alg, pass_key, pass_len,
352: (byte *) pkt, plen + rcv_auth_len, auth_data))
353: DROP("wrong authentication code", pass->id);
354:
355: if (n)
356: n->csn64[pt] = rcv_csn;
357:
358: return 1;
359:
360: drop:
361: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)",
362: (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val);
363:
364: return 0;
365: }
366:
367: /**
368: * ospf_rx_hook
369: * @sk: socket we received the packet.
370: * @len: length of the packet
371: *
372: * This is the entry point for messages from neighbors. Many checks (like
373: * authentication, checksums, size) are done before the packet is passed to
374: * non generic functions.
375: */
376: int
377: ospf_rx_hook(sock *sk, uint len)
378: {
379: /* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter
380: out other packets at kernel level and we receive all packets on all sockets */
381: if (sk->lifindex != sk->iface->index)
382: return 1;
383:
384: DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
385: sk->iface->name, sk->faddr, sk->laddr);
386:
387: /* Initially, the packet is associated with the 'master' iface */
388: struct ospf_iface *ifa = sk->data;
389: struct ospf_proto *p = ifa->oa->po;
390: const char *err_dsc = NULL;
391: uint err_val = 0;
392:
393: /* Should not happen */
394: if (ifa->state <= OSPF_IS_LOOP)
395: return 1;
396:
397: int src_local, dst_local, dst_mcast;
398: src_local = ipa_in_netX(sk->faddr, &ifa->addr->prefix);
399: dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
400: dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers);
401:
402: if (ospf_is_v2(p))
403: {
404: /* First, we eliminate packets with strange address combinations.
405: * In OSPFv2, they might be for other ospf_ifaces (with different IP
406: * prefix) on the same real iface, so we don't log it. We enforce
407: * that (src_local || dst_local), therefore we are eliminating all
408: * such cases.
409: */
410: if (dst_mcast && !src_local)
411: return 1;
412: if (!dst_mcast && !dst_local)
413: return 1;
414:
415: /* Ignore my own broadcast packets */
416: if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
417: return 1;
418: }
419: else
420: {
421: /* In OSPFv3, src_local and dst_local mean link-local.
422: * RFC 5340 says that local (non-vlink) packets use
423: * link-local src address, but does not enforce it. Strange.
424: */
425: if (dst_mcast && !src_local)
426: LOG_PKT_WARN("Multicast packet received from non-link-local %I via %s",
427: sk->faddr, ifa->ifname);
428: }
429:
430: /* Second, we check packet length, checksum, and the protocol version */
431: struct ospf_packet *pkt = (void *) sk_rx_buffer(sk, &len);
432:
433:
434: if (pkt == NULL)
435: DROP("bad IP header", len);
436:
437: if (len < sizeof(struct ospf_packet))
438: DROP("too short", len);
439:
440: if (pkt->version != ospf_get_version(p))
441: DROP("version mismatch", pkt->version);
442:
443: uint plen = ntohs(pkt->length);
444: if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0))
445: DROP("invalid length", plen);
446:
447: if (sk->flags & SKF_TRUNCATED)
448: {
449: /* If we have dynamic buffers and received truncated message, we expand RX buffer */
450:
451: uint bs = plen + 256;
452: bs = BIRD_ALIGN(bs, 1024);
453:
454: if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
455: sk_set_rbsize(sk, bs);
456:
457: DROP("truncated", plen);
458: }
459:
460: if (plen > len)
461: DROP("length mismatch", plen);
462:
463: if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT))
464: {
465: uint hlen = sizeof(struct ospf_packet) + sizeof(union ospf_auth2);
466: uint blen = plen - hlen;
467: void *body = ((void *) pkt) + hlen;
468:
469: if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
470: DROP("invalid checksum", ntohs(pkt->checksum));
471: }
472:
473: /* Third, we resolve associated iface and handle vlinks. */
474:
475: u32 areaid = ntohl(pkt->areaid);
476: u32 rid = ntohl(pkt->routerid);
477: u8 instance_id = pkt->instance_id;
478:
479: if (areaid == ifa->oa->areaid)
480: {
481: /* Matching area ID */
482:
483: if (instance_id != ifa->instance_id)
484: return 1;
485:
486: /* It is real iface, source should be local (in OSPFv2) */
487: if (ospf_is_v2(p) && !src_local)
488: DROP1("strange source address");
489:
490: goto found;
491: }
492: else if ((areaid == 0) && !dst_mcast)
493: {
494: /* Backbone area ID and possible vlink packet */
495:
496: if ((p->areano == 1) || !oa_is_ext(ifa->oa))
497: return 1;
498:
499: struct ospf_iface *iff = NULL;
500: WALK_LIST(iff, p->iface_list)
501: {
502: if ((iff->type == OSPF_IT_VLINK) &&
503: (iff->voa == ifa->oa) &&
504: (iff->instance_id == instance_id) &&
505: (iff->vid == rid))
506: {
507: /* Vlink should be UP */
508: if (iff->state != OSPF_IS_PTP)
509: return 1;
510:
511: ifa = iff;
512: goto found;
513: }
514: }
515:
516: /*
517: * Cannot find matching vlink. It is either misconfigured vlink; NBMA or
518: * PtMP with misconfigured area ID, or packet for some other instance (that
519: * is possible even if instance_id == ifa->instance_id, because it may be
520: * also vlink packet in the other instance, which is different namespace).
521: */
522:
523: return 1;
524: }
525: else
526: {
527: /* Non-matching area ID but cannot be vlink packet */
528:
529: if (instance_id != ifa->instance_id)
530: return 1;
531:
532: DROP("area mismatch", areaid);
533: }
534:
535:
536: found:
537: if (ifa->stub) /* This shouldn't happen */
538: return 1;
539:
540: if (ipa_equal(sk->laddr, ifa->des_routers) && (ifa->sk_dr == 0))
541: return 1;
542:
543: /* TTL check must be done after instance dispatch */
544: if (ifa->check_ttl && (sk->rcv_ttl < 255))
545: DROP("wrong TTL", sk->rcv_ttl);
546:
547: if (rid == p->router_id)
548: DROP1("my own router ID");
549:
550: if (rid == 0)
551: DROP1("zero router ID");
552:
553: /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
554: uint t = ifa->type;
555: struct ospf_neighbor *n;
556: if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
557: n = find_neigh_by_ip(ifa, sk->faddr);
558: else
559: n = find_neigh(ifa, rid);
560:
561: if (!n && (pkt->type != HELLO_P))
562: {
563: OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I",
564: rid, ifa->ifname, sk->faddr);
565: return 1;
566: }
567:
568: /* Check packet type here, ospf_pkt_checkauth3() expects valid values */
569: if (pkt->type < HELLO_P || pkt->type > LSACK_P)
570: DROP("invalid packet type", pkt->type);
571:
572: /* ospf_pkt_checkauth() has its own error logging */
573: if ((ospf_is_v2(p) ?
574: !ospf_pkt_checkauth2(n, ifa, pkt, len) :
575: !ospf_pkt_checkauth3(n, ifa, pkt, len, sk->faddr)))
576: return 1;
577:
578: switch (pkt->type)
579: {
580: case HELLO_P:
581: ospf_receive_hello(pkt, ifa, n, sk->faddr);
582: break;
583:
584: case DBDES_P:
585: ospf_receive_dbdes(pkt, ifa, n);
586: break;
587:
588: case LSREQ_P:
589: ospf_receive_lsreq(pkt, ifa, n);
590: break;
591:
592: case LSUPD_P:
593: ospf_receive_lsupd(pkt, ifa, n);
594: break;
595:
596: case LSACK_P:
597: ospf_receive_lsack(pkt, ifa, n);
598: break;
599: };
600: return 1;
601:
602: drop:
603: LOG_PKT("Bad packet from %I via %s - %s (%u)",
604: sk->faddr, ifa->ifname, err_dsc, err_val);
605:
606: return 1;
607: }
608:
609: /*
610: void
611: ospf_tx_hook(sock * sk)
612: {
613: struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
614: // struct proto *p = (struct proto *) (ifa->oa->p);
615: log(L_ERR "OSPF: TX hook called on %s", ifa->ifname);
616: }
617: */
618:
619: void
620: ospf_err_hook(sock * sk, int err)
621: {
622: struct ospf_iface *ifa = (struct ospf_iface *) (sk->data);
623: struct ospf_proto *p = ifa->oa->po;
624: log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->ifname, err);
625: }
626:
627: void
628: ospf_verr_hook(sock *sk, int err)
629: {
630: struct ospf_proto *p = (struct ospf_proto *) (sk->data);
631: log(L_ERR "%s: Vlink socket error: %M", p->p.name, err);
632: }
633:
634: void
635: ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
636: {
637: sock *sk = ifa->sk;
638: struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
639: uint plen = ntohs(pkt->length);
640:
641: if (ospf_is_v2(ifa->oa->po))
642: ospf_pkt_finalize2(ifa, pkt, &plen);
643: else
644: ospf_pkt_finalize3(ifa, pkt, &plen, sk->saddr);
645:
646: int done = sk_send_to(sk, plen, dst, 0);
647: if (!done)
648: log(L_WARN "OSPF: TX queue full on %s", ifa->ifname);
649: }
650:
651: void
652: ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
653: {
654: struct ospf_neighbor *n;
655:
656: WALK_LIST(n, ifa->neigh_list)
657: if (n->state >= state)
658: ospf_send_to(ifa, n->ip);
659: }
660:
661: void
662: ospf_send_to_bdr(struct ospf_iface *ifa)
663: {
664: if (ipa_nonzero2(ifa->drip))
665: ospf_send_to(ifa, ifa->drip);
666: if (ipa_nonzero2(ifa->bdrip))
667: ospf_send_to(ifa, ifa->bdrip);
668: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>