From f7b32ed0620937ad5287c6790d88424c43e9a090 Mon Sep 17 00:00:00 2001
From: Jeffrey Pfau <jeffrey@endrift.com>
Date: Sat, 12 May 2012 14:13:16 -0700
Subject: [PATCH] avahi-daemon: add support for whitelisting and blacklisting
IP addresses
---
avahi-core/addr-util.h | 8 ++++
avahi-core/core.h | 3 ++
avahi-core/iface.c | 15 +++++++
avahi-core/server.c | 93 +++++++++++++++++++++++++++++++---------
avahi-daemon/avahi-daemon.conf | 2 +
avahi-daemon/main.c | 34 +++++++++++++++
man/avahi-daemon.conf.5.xml.in | 16 +++++++
7 files changed, 150 insertions(+), 21 deletions(-)
diff --git a/avahi-core/addr-util.h b/avahi-core/addr-util.h
index 66a9422..cc38a66 100644
|
a
|
b
|
|
| 25 | 25 | |
| 26 | 26 | #include <avahi-common/cdecl.h> |
| 27 | 27 | #include <avahi-common/address.h> |
| | 28 | #include <avahi-common/llist.h> |
| 28 | 29 | |
| 29 | 30 | AVAHI_C_DECL_BEGIN |
| 30 | 31 | |
| … |
… |
|
| 42 | 43 | * returns 1 if yes, 0 otherwise */ |
| 43 | 44 | int avahi_address_is_link_local(const AvahiAddress *a); |
| 44 | 45 | |
| | 46 | typedef struct AvahiAddressList AvahiAddressList; |
| | 47 | |
| | 48 | struct AvahiAddressList { |
| | 49 | AvahiAddress address; |
| | 50 | AVAHI_LLIST_FIELDS(AvahiAddressList, address); |
| | 51 | }; |
| | 52 | |
| 45 | 53 | AVAHI_C_DECL_END |
| 46 | 54 | |
| 47 | 55 | #endif |
diff --git a/avahi-core/core.h b/avahi-core/core.h
index f50c612..0e2bfa5 100644
|
a
|
b
|
|
| 31 | 31 | #include <avahi-common/watch.h> |
| 32 | 32 | #include <avahi-common/timeval.h> |
| 33 | 33 | #include <avahi-core/rr.h> |
| | 34 | #include <avahi-core/addr-util.h> |
| 34 | 35 | |
| 35 | 36 | AVAHI_C_DECL_BEGIN |
| 36 | 37 | |
| … |
… |
|
| 48 | 49 | int use_ipv6; /**< Enable IPv6 support */ |
| 49 | 50 | AvahiStringList *allow_interfaces;/**< Allow specific interface to be used for Avahi */ |
| 50 | 51 | AvahiStringList *deny_interfaces; /**< Deny specific interfaces to be used for Avahi */ |
| | 52 | AVAHI_LLIST_HEAD(AvahiAddressList, allow_addresses); /**< Allow specific IP addresses to be used for Avahi */ |
| | 53 | AVAHI_LLIST_HEAD(AvahiAddressList, deny_addresses); /**< Deny specific IP addresses to be used for Avahi */ |
| 51 | 54 | int publish_hinfo; /**< Register a HINFO record for the host containing the local OS and CPU type */ |
| 52 | 55 | int publish_addresses; /**< Register A, AAAA and PTR records for all local IP addresses */ |
| 53 | 56 | int publish_workstation; /**< Register a _workstation._tcp service */ |
diff --git a/avahi-core/iface.c b/avahi-core/iface.c
index 39a860a..5b3b313 100644
|
a
|
b
|
|
| 698 | 698 | |
| 699 | 699 | int avahi_interface_address_is_relevant(AvahiInterfaceAddress *a) { |
| 700 | 700 | AvahiInterfaceAddress *b; |
| | 701 | AvahiAddressList *l; |
| 701 | 702 | assert(a); |
| 702 | 703 | |
| | 704 | for (l = a->monitor->server->config.deny_addresses; l; l = l->address_next) |
| | 705 | if (avahi_address_cmp(&l->address, &a->address) == 0) |
| | 706 | return 0; |
| | 707 | |
| | 708 | if (a->monitor->server->config.allow_addresses) { |
| | 709 | |
| | 710 | for (l = a->monitor->server->config.allow_addresses; l; l = l->address_next) |
| | 711 | if (avahi_address_cmp(&l->address, &a->address) == 0) |
| | 712 | goto good; |
| | 713 | |
| | 714 | return 0; |
| | 715 | } |
| | 716 | |
| | 717 | good: |
| 703 | 718 | /* Publish public and non-deprecated IP addresses */ |
| 704 | 719 | if (a->global_scope && !a->deprecated) |
| 705 | 720 | return 1; |
diff --git a/avahi-core/server.c b/avahi-core/server.c
index 69a1d02..e5b540e 100644
|
a
|
b
|
|
| 1579 | 1579 | c->use_ipv4 = 1; |
| 1580 | 1580 | c->allow_interfaces = NULL; |
| 1581 | 1581 | c->deny_interfaces = NULL; |
| | 1582 | AVAHI_LLIST_HEAD_INIT(AvahiAddressList, c->allow_addresses); |
| | 1583 | AVAHI_LLIST_HEAD_INIT(AvahiAddressList, c->deny_addresses); |
| 1582 | 1584 | c->host_name = NULL; |
| 1583 | 1585 | c->domain_name = NULL; |
| 1584 | 1586 | c->check_response_ttl = 0; |
| … |
… |
|
| 1606 | 1608 | } |
| 1607 | 1609 | |
| 1608 | 1610 | void avahi_server_config_free(AvahiServerConfig *c) { |
| | 1611 | AvahiAddressList *l, *next; |
| 1609 | 1612 | assert(c); |
| 1610 | 1613 | |
| 1611 | 1614 | avahi_free(c->host_name); |
| … |
… |
|
| 1613 | 1616 | avahi_string_list_free(c->browse_domains); |
| 1614 | 1617 | avahi_string_list_free(c->allow_interfaces); |
| 1615 | 1618 | avahi_string_list_free(c->deny_interfaces); |
| | 1619 | for (l = c->allow_addresses; l; l = next) { |
| | 1620 | next = l->address_next; |
| | 1621 | avahi_free(l); |
| | 1622 | } |
| | 1623 | for (l = c->deny_addresses; l; l = next) { |
| | 1624 | next = l->address_next; |
| | 1625 | avahi_free(l); |
| | 1626 | } |
| 1616 | 1627 | } |
| 1617 | 1628 | |
| 1618 | 1629 | AvahiServerConfig* avahi_server_config_copy(AvahiServerConfig *ret, const AvahiServerConfig *c) { |
| 1619 | 1630 | char *d = NULL, *h = NULL; |
| 1620 | 1631 | AvahiStringList *browse = NULL, *allow = NULL, *deny = NULL; |
| | 1632 | AvahiAddressList *l, *next, *allow_addresses = NULL, *deny_addresses = NULL; |
| 1621 | 1633 | assert(ret); |
| 1622 | 1634 | assert(c); |
| 1623 | 1635 | |
| … |
… |
|
| 1626 | 1638 | return NULL; |
| 1627 | 1639 | |
| 1628 | 1640 | if (c->domain_name) |
| 1629 | | if (!(d = avahi_strdup(c->domain_name))) { |
| 1630 | | avahi_free(h); |
| 1631 | | return NULL; |
| | 1641 | if (!(d = avahi_strdup(c->domain_name))) |
| | 1642 | goto clean; |
| | 1643 | |
| | 1644 | if (!(browse = avahi_string_list_copy(c->browse_domains)) && c->browse_domains) |
| | 1645 | goto clean; |
| | 1646 | |
| | 1647 | if (!(allow = avahi_string_list_copy(c->allow_interfaces)) && c->allow_interfaces) |
| | 1648 | goto clean; |
| | 1649 | |
| | 1650 | if (!(deny = avahi_string_list_copy(c->deny_interfaces)) && c->deny_interfaces) |
| | 1651 | goto clean; |
| | 1652 | |
| | 1653 | if (c->allow_addresses) { |
| | 1654 | if (!(allow_addresses = avahi_new(AvahiAddressList, 1))) |
| | 1655 | goto clean; |
| | 1656 | AVAHI_LLIST_INIT(AvahiAddressList, address, allow_addresses); |
| | 1657 | for (l = c->allow_addresses; l; l = l->address_next) { |
| | 1658 | if (!(next = avahi_new(AvahiAddressList, 1))) |
| | 1659 | goto clean; |
| | 1660 | AVAHI_LLIST_INIT(AvahiAddressList, address, next); |
| | 1661 | next->address = l->address; |
| | 1662 | AVAHI_LLIST_PREPEND(AvahiAddressList, address, allow_addresses, next); |
| 1632 | 1663 | } |
| 1633 | | |
| 1634 | | if (!(browse = avahi_string_list_copy(c->browse_domains)) && c->browse_domains) { |
| 1635 | | avahi_free(h); |
| 1636 | | avahi_free(d); |
| 1637 | | return NULL; |
| 1638 | 1664 | } |
| 1639 | 1665 | |
| 1640 | | if (!(allow = avahi_string_list_copy(c->allow_interfaces)) && c->allow_interfaces) { |
| 1641 | | avahi_string_list_free(browse); |
| 1642 | | avahi_free(h); |
| 1643 | | avahi_free(d); |
| 1644 | | return NULL; |
| 1645 | | } |
| 1646 | | |
| 1647 | | if (!(deny = avahi_string_list_copy(c->deny_interfaces)) && c->deny_interfaces) { |
| 1648 | | avahi_string_list_free(allow); |
| 1649 | | avahi_string_list_free(browse); |
| 1650 | | avahi_free(h); |
| 1651 | | avahi_free(d); |
| 1652 | | return NULL; |
| | 1666 | if (c->deny_addresses) { |
| | 1667 | if (!(deny_addresses = avahi_new(AvahiAddressList, 1))) |
| | 1668 | goto clean; |
| | 1669 | AVAHI_LLIST_INIT(AvahiAddressList, address, allow_addresses); |
| | 1670 | for (l = c->deny_addresses; l; l = l->address_next) { |
| | 1671 | if (!(next = avahi_new(AvahiAddressList, 1))) |
| | 1672 | goto clean; |
| | 1673 | AVAHI_LLIST_INIT(AvahiAddressList, address, next); |
| | 1674 | next->address = l->address; |
| | 1675 | AVAHI_LLIST_PREPEND(AvahiAddressList, address, deny_addresses, next); |
| | 1676 | } |
| 1653 | 1677 | } |
| 1654 | 1678 | |
| 1655 | 1679 | *ret = *c; |
| … |
… |
|
| 1658 | 1682 | ret->browse_domains = browse; |
| 1659 | 1683 | ret->allow_interfaces = allow; |
| 1660 | 1684 | ret->deny_interfaces = deny; |
| | 1685 | ret->allow_addresses = allow_addresses; |
| | 1686 | ret->deny_addresses = deny_addresses; |
| 1661 | 1687 | |
| 1662 | 1688 | return ret; |
| | 1689 | |
| | 1690 | clean: |
| | 1691 | if (deny_addresses) { |
| | 1692 | for (l = deny_addresses; l; l = next) { |
| | 1693 | next = l->address_next; |
| | 1694 | avahi_free(l); |
| | 1695 | } |
| | 1696 | } |
| | 1697 | if (allow_addresses) { |
| | 1698 | for (l = allow_addresses; l; l = next) { |
| | 1699 | next = l->address_next; |
| | 1700 | avahi_free(l); |
| | 1701 | } |
| | 1702 | } |
| | 1703 | if (deny) |
| | 1704 | avahi_string_list_free(deny); |
| | 1705 | if (allow) |
| | 1706 | avahi_string_list_free(allow); |
| | 1707 | if (browse) |
| | 1708 | avahi_string_list_free(browse); |
| | 1709 | if (h) |
| | 1710 | avahi_free(h); |
| | 1711 | if (d) |
| | 1712 | avahi_free(d); |
| | 1713 | return NULL; |
| 1663 | 1714 | } |
| 1664 | 1715 | |
| 1665 | 1716 | int avahi_server_errno(AvahiServer *s) { |
diff --git a/avahi-daemon/avahi-daemon.conf b/avahi-daemon/avahi-daemon.conf
index 27e240d..77181bd 100644
|
a
|
b
|
|
| 26 | 26 | use-ipv6=no |
| 27 | 27 | #allow-interfaces=eth0 |
| 28 | 28 | #deny-interfaces=eth1 |
| | 29 | #allow-addresses=192.168.50.10, 192.168.50.11 |
| | 30 | #deny-addresses=192.168.50.20, 192.168.50.21 |
| 29 | 31 | #check-response-ttl=no |
| 30 | 32 | #use-iff-running=no |
| 31 | 33 | #enable-dbus=yes |
diff --git a/avahi-daemon/main.c b/avahi-daemon/main.c
index d46f40a..6ab5861 100644
|
a
|
b
|
|
| 667 | 667 | c->server_config.deny_interfaces = avahi_string_list_add(c->server_config.deny_interfaces, *t); |
| 668 | 668 | |
| 669 | 669 | avahi_strfreev(e); |
| | 670 | } else if (strcasecmp(p->key, "allow-addresses") == 0) { |
| | 671 | char **e, **t; |
| | 672 | |
| | 673 | e = avahi_split_csv(p->value); |
| | 674 | |
| | 675 | for (t = e; *t; t++) { |
| | 676 | AvahiAddressList *l = avahi_new(AvahiAddressList, 1); |
| | 677 | AVAHI_LLIST_INIT(AvahiAddressList, address, l); |
| | 678 | if (!avahi_address_parse(*t, AVAHI_PROTO_UNSPEC, &l->address)) { |
| | 679 | avahi_log_error("Invalid allow-addresses setting %s", p->value); |
| | 680 | avahi_strfreev(e); |
| | 681 | goto finish; |
| | 682 | } |
| | 683 | AVAHI_LLIST_PREPEND(AvahiAddressList, address, c->server_config.allow_addresses, l); |
| | 684 | } |
| | 685 | |
| | 686 | avahi_strfreev(e); |
| | 687 | } else if (strcasecmp(p->key, "deny-addresses") == 0) { |
| | 688 | char **e, **t; |
| | 689 | |
| | 690 | e = avahi_split_csv(p->value); |
| | 691 | |
| | 692 | for (t = e; *t; t++) { |
| | 693 | AvahiAddressList *l = avahi_new(AvahiAddressList, 1); |
| | 694 | AVAHI_LLIST_INIT(AvahiAddressList, address, l); |
| | 695 | if (!avahi_address_parse(*t, AVAHI_PROTO_UNSPEC, &l->address)) { |
| | 696 | avahi_log_error("Invalid deny-addresses setting %s", p->value); |
| | 697 | avahi_strfreev(e); |
| | 698 | goto finish; |
| | 699 | } |
| | 700 | AVAHI_LLIST_PREPEND(AvahiAddressList, address, c->server_config.deny_addresses, l); |
| | 701 | } |
| | 702 | |
| | 703 | avahi_strfreev(e); |
| 670 | 704 | } else if (strcasecmp(p->key, "ratelimit-interval-usec") == 0) { |
| 671 | 705 | AvahiUsec k; |
| 672 | 706 | |
diff --git a/man/avahi-daemon.conf.5.xml.in b/man/avahi-daemon.conf.5.xml.in
index bea7ed5..af8208b 100644
|
a
|
b
|
|
| 86 | 86 | </option> |
| 87 | 87 | |
| 88 | 88 | <option> |
| | 89 | <p><opt>allow-addresses=</opt> Set a comma separated list of |
| | 90 | IP addresses that should be used by the avahi-daemon. |
| | 91 | Traffic on other IP addresses will be ignored. If set to an |
| | 92 | empty list all local IP addresses on the specified network |
| | 93 | interfaces will be used.</p> |
| | 94 | </option> |
| | 95 | |
| | 96 | <option> |
| | 97 | <p><opt>deny-addresses=</opt> Set a comma separated list of |
| | 98 | IP addresses that should be ignored by avahi-daemon. Other |
| | 99 | not specified IP addresses will be used, unless |
| | 100 | <opt>allow-addresses=</opt> is set. This option takes |
| | 101 | precedence over <opt>allow-addresses=</opt>.</p> |
| | 102 | </option> |
| | 103 | |
| | 104 | <option> |
| 89 | 105 | <p><opt>check-response-ttl=</opt> Takes a boolean value ("yes" |
| 90 | 106 | or "no"). If set to "yes", an additional security check is |
| 91 | 107 | activated: incoming IP packets will be ignored unless the IP |