diff --git a/SOURCES/dhclient-script b/SOURCES/dhclient-script index d985454..7d486cf 100644 --- a/SOURCES/dhclient-script +++ b/SOURCES/dhclient-script @@ -127,9 +127,13 @@ make_resolv_conf() { echo "options ${RES_OPTIONS}" >> ${rscf} fi - for nameserver in ${new_domain_name_servers} ; do - echo "nameserver ${nameserver}" >> ${rscf} - done + if [ -n "${new_domain_name_servers}" ]; then + for nameserver in ${new_domain_name_servers} ; do + echo "nameserver ${nameserver}" >> "${rscf}" + done + else # keep 'old' nameservers + sed -n /^\w*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p /etc/resolv.conf >> "${rscf}" + fi change_resolv_conf ${rscf} rm -f ${rscf} @@ -159,19 +163,23 @@ make_resolv_conf() { echo "options ${RES_OPTIONS}" >> ${rscf} fi - shopt -s nocasematch - for nameserver in ${new_dhcp6_name_servers} ; do - # If the nameserver has a link-local address - # add a (interface name) to it. - if [[ "$nameserver" =~ ^fe80:: ]] - then - zone_id="%${interface}" - else - zone_id= - fi - echo "nameserver ${nameserver}$zone_id" >> ${rscf} - done - shopt -u nocasematch + shopt -s nocasematch + if [ -n "${new_dhcp6_name_servers}" ]; then + for nameserver in ${new_dhcp6_name_servers} ; do + # If the nameserver has a link-local address + # add a (interface name) to it. + if [[ "$nameserver" =~ ^fe80:: ]] + then + zone_id="%${interface}" + else + zone_id= + fi + echo "nameserver ${nameserver}$zone_id" >> "${rscf}" + done + else # keep 'old' nameservers + sed -n /^\w*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p /etc/resolv.conf >> "${rscf}" + fi + shopt -u nocasematch change_resolv_conf ${rscf} rm -f ${rscf} @@ -327,6 +335,14 @@ dhconfig() { flush_dev ${interface} fi + # make sure the interface is up + ip link set dev ${interface} up + + # replace = add if it doesn't exist or override (update lifetimes) if it's there + ip -4 addr replace ${new_ip_address}/${new_prefix} broadcast ${new_broadcast_address} dev ${interface} \ + valid_lft ${new_dhcp_lease_time} preferred_lft ${new_dhcp_lease_time} >/dev/null 2>&1 + + if [ "${reason}" = "BOUND" ] || [ "${reason}" = "REBOOT" ] || [ ! "${old_ip_address}" = "${new_ip_address}" ] || [ ! "${old_subnet_mask}" = "${new_subnet_mask}" ] || @@ -334,10 +350,7 @@ dhconfig() { [ ! "${old_broadcast_address}" = "${new_broadcast_address}" ] || [ ! "${old_routers}" = "${new_routers}" ] || [ ! "${old_interface_mtu}" = "${new_interface_mtu}" ]; then - ip -4 addr add ${new_ip_address}/${new_prefix} broadcast ${new_broadcast_address} dev ${interface} \ - valid_lft ${new_dhcp_lease_time} preferred_lft ${new_dhcp_lease_time} >/dev/null 2>&1 - ip link set dev ${interface} up - + # The 576 MTU is only used for X.25 and dialup connections # where the admin wants low latency. Such a low MTU can cause # problems with UDP traffic, among other things. As such, @@ -352,6 +365,9 @@ dhconfig() { [ -n "${new_static_routes}" ]; then if [ -n "${new_classless_static_routes}" ]; then IFS=', |' static_routes=(${new_classless_static_routes}) + # If the DHCP server returns both a Classless Static Routes option and + # a Router option, the DHCP client MUST ignore the Router option. (RFC3442) + new_routers="" else IFS=', |' static_routes=(${new_static_routes}) fi @@ -360,11 +376,9 @@ dhconfig() { for((i=0; i<${#static_routes[@]}; i+=2)); do target=${static_routes[$i]} if [ -n "${new_classless_static_routes}" ]; then - if [ ${target} = "0" ]; then - # If the DHCP server returns both a Classless Static Routes option and - # a Router option, the DHCP client MUST ignore the Router option. (RFC3442) - new_routers="" - prefix="0" + if [ ${target} = "0" ]; then + new_routers="${static_routes[$i+1]}" + continue else prefix=${target%%.*} target=${target#*.} @@ -462,17 +476,13 @@ dhconfig() { fi fi fi - - else # RENEW||REBIND - only update address lifetimes - ip -4 addr change ${new_ip_address}/${new_prefix} broadcast ${new_broadcast_address} dev ${interface} \ - valid_lft ${new_dhcp_lease_time} preferred_lft ${new_dhcp_lease_time} >/dev/null 2>&1 fi if [ ! "${new_ip_address}" = "${alias_ip_address}" ] && [ -n "${alias_ip_address}" ]; then # Reset the alias address (fix: this should really only do this on changes) ip -4 addr flush dev ${interface} label ${interface}:0 >/dev/null 2>&1 - ip -4 addr add ${alias_ip_address}/${alias_prefix} broadcast ${alias_broadcast_address} dev ${interface} label ${interface}:0 + ip -4 addr replace ${alias_ip_address}/${alias_prefix} broadcast ${alias_broadcast_address} dev ${interface} label ${interface}:0 ip -4 route replace ${alias_ip_address}/32 dev ${interface} fi @@ -528,7 +538,7 @@ dhconfig() { # the addresses in any IAs it receives in the Reply message before # using that address for traffic. add_ipv6_addr_with_DAD() { - ip -6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \ + ip -6 addr replace ${new_ip6_address}/${new_ip6_prefixlen} \ dev ${interface} scope global valid_lft ${new_max_life} \ preferred_lft ${new_preferred_life} @@ -586,12 +596,11 @@ dh6config() { if [[ -n "${new_ip6_address}" ]] && [[ -n "${new_ip6_prefixlen}" ]]; then if [[ ! "${new_ip6_address}" = "${old_ip6_address}" ]]; then + [[ -n "${old_ip6_address}" ]] && ip -6 addr del ${old_ip6_address} dev ${interface} add_ipv6_addr_with_DAD - else # only update address lifetimes - ip -6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \ - dev ${interface} scope global valid_lft ${new_max_life} \ - preferred_lft ${new_preferred_life} fi + # call it even if new_ip6_address = old_ip6_address to update lifetimes + add_ipv6_addr_with_DAD fi if [ ! "${new_dhcp6_name_servers}" = "${old_dhcp6_name_servers}" ] || @@ -766,7 +775,7 @@ case "${reason}" in fi if [ -n "${alias_ip_address}" ]; then - ip -4 addr add ${alias_ip_address}/${alias_prefix} broadcast ${alias_broadcast_address} dev ${interface} label ${interface}:0 + ip -4 addr replace ${alias_ip_address}/${alias_prefix} broadcast ${alias_broadcast_address} dev ${interface} label ${interface}:0 ip -4 route replace ${alias_ip_address}/32 dev ${interface} fi @@ -779,7 +788,7 @@ case "${reason}" in ip -4 addr flush dev ${interface} label ${interface}:0 >/dev/null 2>&1 fi - ip -4 addr add ${new_ip_address}/${new_prefix} \ + ip -4 addr replace ${new_ip_address}/${new_prefix} \ broadcast ${new_broadcast_address} dev ${interface} \ valid_lft ${new_dhcp_lease_time} preferred_lft ${new_dhcp_lease_time} set ${new_routers} diff --git a/SOURCES/dhcp-4.2.5-centos-branding.patch b/SOURCES/dhcp-4.2.5-centos-branding.patch deleted file mode 100644 index f3e7113..0000000 --- a/SOURCES/dhcp-4.2.5-centos-branding.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff -uNrp dhcp-4.1.1-P1.orig/omapip/errwarn.c dhcp-4.1.1-P1/omapip/errwarn.c ---- dhcp-4.1.1-P1.orig/omapip/errwarn.c 2012-08-15 14:04:33.149141000 +0000 -+++ dhcp-4.1.1-P1/omapip/errwarn.c 2012-08-15 14:13:05.582416057 +0000 -@@ -81,8 +81,8 @@ void log_fatal (const char * fmt, ... ) - log_error ("have been made to the base software release in order to make"); - log_error ("it work better with this distribution."); - log_error ("%s", ""); -- log_error ("Please report for this software via the Red Hat Bugzilla site:"); -- log_error (" http://bugzilla.redhat.com"); -+ log_error ("Please report for this software via the CentOS Bugs Database:"); -+ log_error (" http://bugs.centos.org/"); - log_error ("%s", ""); - log_error ("exiting."); - #endif diff --git a/SOURCES/dhcp-addignore.patch b/SOURCES/dhcp-addignore.patch new file mode 100644 index 0000000..c97e979 --- /dev/null +++ b/SOURCES/dhcp-addignore.patch @@ -0,0 +1,147 @@ +diff -Naur ./common/conflex.c ../dhcp-4.2.5/common/conflex.c +--- ./common/conflex.c 2016-02-11 13:03:38.892135723 +0100 ++++ ../dhcp-4.2.5/common/conflex.c 2016-02-11 13:05:18.447135723 +0100 +@@ -1067,6 +1067,8 @@ + return IF; + if (!strcasecmp (atom + 1, "s")) + return IS; ++ if (!strcasecmp (atom + 1, "gnore-client-uids")) ++ return IGNORE_CLIENT_UIDS; + if (!strcasecmp (atom + 1, "gnore")) + return IGNORE; + break; +diff -Naur ./includes/dhcpd.h ../dhcp-4.2.5/includes/dhcpd.h +--- ./includes/dhcpd.h 2016-02-11 13:03:38.903135723 +0100 ++++ ../dhcp-4.2.5/includes/dhcpd.h 2016-02-11 13:12:20.398135723 +0100 +@@ -766,6 +766,8 @@ + #endif + #endif + ++#define SV_IGNORE_CLIENT_UIDS 78 ++ + #if !defined (DEFAULT_DEFAULT_LEASE_TIME) + # define DEFAULT_DEFAULT_LEASE_TIME 43200 + #endif +diff -Naur ./includes/dhctoken.h ../dhcp-4.2.5/includes/dhctoken.h +--- ./includes/dhctoken.h 2016-02-11 13:03:38.901135723 +0100 ++++ ../dhcp-4.2.5/includes/dhctoken.h 2016-02-11 13:13:09.958135723 +0100 +@@ -366,7 +366,8 @@ + SECONDARY6 = 667, + TOKEN_INFINIBAND = 668, + BOOTP_BROADCAST_ALWAYS = 669, +- DESTINATION_DESCRIPTOR = 670 ++ DESTINATION_DESCRIPTOR = 670, ++ IGNORE_CLIENT_UIDS = 671 + }; + + #define is_identifier(x) ((x) >= FIRST_TOKEN && \ +diff -Naur ./server/confpars.c ../dhcp-4.2.5/server/confpars.c +--- ./server/confpars.c 2016-02-11 13:03:38.915135723 +0100 ++++ ../dhcp-4.2.5/server/confpars.c 2016-02-11 13:15:48.269135723 +0100 +@@ -332,6 +332,7 @@ + | ONE_LEASE_PER_CLIENT boolean + | GET_LEASE_HOSTNAMES boolean + | USE_HOST_DECL_NAME boolean ++ | IGNORE_CLIENT_UIDS boolean + | NEXT_SERVER ip-addr-or-hostname SEMI + | option_parameter + | SERVER-IDENTIFIER ip-addr-or-hostname SEMI +@@ -4125,6 +4126,10 @@ + code = SV_LEASEQUERY; + break; + ++ case IGNORE_CLIENT_UIDS: ++ code = SV_IGNORE_CLIENT_UIDS; ++ break; ++ + default: + parse_warn (cfile, "expecting allow/deny key"); + skip_to_semi (cfile); +@@ -4138,7 +4143,6 @@ + status = option_cache(oc, NULL, data, option, MDL); + expression_dereference (&data, MDL); + parse_semi (cfile); +- return status; + } + + void +diff -Naur ./server/dhcp.c ../dhcp-4.2.5/server/dhcp.c +--- ./server/dhcp.c 2016-02-11 13:03:38.916135723 +0100 ++++ ../dhcp-4.2.5/server/dhcp.c 2016-02-11 13:24:06.173135723 +0100 +@@ -2393,34 +2393,39 @@ + /* Update Client Last Transaction Time. */ + lt->cltt = cur_time; + +- /* Record the uid, if given... */ +- oc = lookup_option (&dhcp_universe, packet -> options, +- DHO_DHCP_CLIENT_IDENTIFIER); +- if (!oc) ++ /* See if we want to record the uid for this client */ ++ oc = lookup_option(&server_universe, state->options, ++ SV_IGNORE_CLIENT_UIDS); ++ if ((oc == NULL) || ++ !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, ++ packet->options, state->options, ++ &lease->scope, oc, MDL)) { ++ ++ /* Record the uid, if given... */ + oc = lookup_option (&dhcp_universe, packet -> options, +- DHO_PXE_CLIENT_ID); +- if (oc && +- evaluate_option_cache (&d1, packet, lease, +- (struct client_state *)0, +- packet -> options, state -> options, +- &lease -> scope, oc, MDL)) { +- if (d1.len <= sizeof lt -> uid_buf) { +- memcpy (lt -> uid_buf, d1.data, d1.len); +- lt -> uid = lt -> uid_buf; +- lt -> uid_max = sizeof lt -> uid_buf; +- lt -> uid_len = d1.len; +- } else { +- unsigned char *tuid; +- lt -> uid_max = d1.len; +- lt -> uid_len = d1.len; +- tuid = (unsigned char *)dmalloc (lt -> uid_max, MDL); +- /* XXX inelegant */ +- if (!tuid) +- log_fatal ("no memory for large uid."); +- memcpy (tuid, d1.data, lt -> uid_len); +- lt -> uid = tuid; ++ DHO_DHCP_CLIENT_IDENTIFIER); ++ if (oc && ++ evaluate_option_cache(&d1, packet, lease, NULL, ++ packet->options, state->options, ++ &lease->scope, oc, MDL)) { ++ if (d1.len <= sizeof(lt->uid_buf)) { ++ memcpy(lt->uid_buf, d1.data, d1.len); ++ lt->uid = lt->uid_buf; ++ lt->uid_max = sizeof(lt->uid_buf); ++ lt->uid_len = d1.len; ++ } else { ++ unsigned char *tuid; ++ lt->uid_max = d1.len; ++ lt->uid_len = d1.len; ++ tuid = (unsigned char *)dmalloc(lt->uid_max, MDL); ++ /* XXX inelegant */ ++ if (!tuid) ++ log_fatal ("no memory for large uid."); ++ memcpy(tuid, d1.data, lt->uid_len); ++ lt->uid = tuid; ++ } ++ data_string_forget (&d1, MDL); + } +- data_string_forget (&d1, MDL); + } + + if (host) { +diff -Naur ./server/stables.c ../dhcp-4.2.5/server/stables.c +--- ./server/stables.c 2016-02-11 13:03:38.909135723 +0100 ++++ ../dhcp-4.2.5/server/stables.c 2016-02-11 13:25:00.081135723 +0100 +@@ -266,6 +266,7 @@ + { "ldap-tls-randfile", "t", &server_universe, 77, 1 }, + #endif /* LDAP_USE_SSL */ + #endif /* LDAP_CONFIGURATION */ ++ { "ignore-client-uids", "f", &server_universe, 78, 1 }, + { NULL, NULL, NULL, 0, 0 } + }; + diff --git a/SOURCES/dhcp-max-fd-value.patch b/SOURCES/dhcp-max-fd-value.patch new file mode 100644 index 0000000..fe9bb23 --- /dev/null +++ b/SOURCES/dhcp-max-fd-value.patch @@ -0,0 +1,30 @@ +diff -up dhcp-4.2.5/includes/site.h.max-fd dhcp-4.2.5/includes/site.h +--- dhcp-4.2.5/includes/site.h.max-fd 2016-04-21 15:15:14.618846830 +0200 ++++ dhcp-4.2.5/includes/site.h 2016-04-21 15:17:06.529731652 +0200 +@@ -275,3 +275,9 @@ + Care should be taken before enabling this option. */ + + /* #define SERVER_ID_CHECK */ ++ ++/* Limit the value of a file descriptor the serve will use ++ when accepting a connecting request. This can be used to ++ limit the number of TCP connections that the server will ++ allow at one time. A value of 0 means there is no limit.*/ ++#define MAX_FD_VALUE 200 +diff -up dhcp-4.2.5/omapip/listener.c.max-fd dhcp-4.2.5/omapip/listener.c +--- dhcp-4.2.5/omapip/listener.c.max-fd 2013-01-03 01:02:24.000000000 +0100 ++++ dhcp-4.2.5/omapip/listener.c 2016-04-21 15:15:14.618846830 +0200 +@@ -239,7 +239,12 @@ isc_result_t omapi_accept (omapi_object_ + return ISC_R_NORESOURCES; + return ISC_R_UNEXPECTED; + } +- ++ ++ if ((MAX_FD_VALUE != 0) && (socket > MAX_FD_VALUE)) { ++ close(socket); ++ return (ISC_R_NORESOURCES); ++ } ++ + #if defined (TRACING) + /* If we're recording a trace, remember the connection. */ + if (trace_record ()) { diff --git a/SOURCES/dhcp-prepend.patch b/SOURCES/dhcp-prepend.patch new file mode 100644 index 0000000..0662f46 --- /dev/null +++ b/SOURCES/dhcp-prepend.patch @@ -0,0 +1,65 @@ +diff -up dhcp-4.2.5/client/dhc6.c.prepend dhcp-4.2.5/client/dhc6.c +--- dhcp-4.2.5/client/dhc6.c.prepend 2016-04-18 14:21:41.062502036 +0200 ++++ dhcp-4.2.5/client/dhc6.c 2016-04-18 14:25:11.683732506 +0200 +@@ -595,7 +595,7 @@ dhc6_dup_addr(struct dhc6_addr *addr, co + * Parsed options are deleted in order to not save them in the lease file. + */ + static struct dhc6_lease * +-dhc6_leaseify(struct packet *packet) ++dhc6_leaseify(struct packet *packet, struct client_state* client) + { + struct data_string ds; + struct dhc6_lease *lease; +@@ -687,6 +687,11 @@ dhc6_leaseify(struct packet *packet) + lease->server_id.data, 52)); + } + ++ execute_statements_in_scope(NULL, (struct packet *)packet, NULL, ++ client, lease->options, lease->options, ++ &global_scope, client->config->on_receipt, ++ NULL); ++ + return lease; + } + +@@ -2892,7 +2897,7 @@ init_handler(struct packet *packet, stru + return; + } + +- lease = dhc6_leaseify(packet); ++ lease = dhc6_leaseify(packet, client); + + if (dhc6_check_advertise(lease) != ISC_R_SUCCESS) { + log_debug("PRC: Lease failed to satisfy."); +@@ -2975,6 +2980,12 @@ info_request_handler(struct packet *pack + option_state_reference(&client->active_lease->options, + packet->options, MDL); + ++ execute_statements_in_scope(NULL, (struct packet *)packet, NULL, client, ++ client->active_lease->options, ++ client->active_lease->options, ++ &global_scope, client->config->on_receipt, ++ NULL); ++ + start_informed(client); + } + +@@ -3009,7 +3020,7 @@ rapid_commit_handler(struct packet *pack + return; + } + +- lease = dhc6_leaseify(packet); ++ lease = dhc6_leaseify(packet, client); + + /* This is an out of memory condition...hopefully a temporary + * problem. Returning now makes us try to retransmit later. +@@ -3823,7 +3834,7 @@ reply_handler(struct packet *packet, str + return; + } + +- lease = dhc6_leaseify(packet); ++ lease = dhc6_leaseify(packet, client); + + /* This is an out of memory condition...hopefully a temporary + * problem. Returning now makes us try to retransmit later. +diff -up dhcp-4.2.5/RELNOTES.prepend dhcp-4.2.5/RELNOTES diff --git a/SPECS/dhcp.spec b/SPECS/dhcp.spec index 6fff925..87da074 100644 --- a/SPECS/dhcp.spec +++ b/SPECS/dhcp.spec @@ -18,7 +18,7 @@ Summary: Dynamic host configuration protocol software Name: dhcp Version: 4.2.5 -Release: 42%{?dist} +Release: 47%{?dist} # NEVER CHANGE THE EPOCH on this package. The previous maintainer (prior to # dcantrell maintaining the package) made incorrect use of the epoch and # that's why it is at 12 now. It should have never been used, but it was. @@ -90,7 +90,9 @@ Patch56: dhcp-vlanfilter.patch Patch57: dhcp-option97-pxe-client-id.patch Patch58: dhcp-client-request-release-bind-iface.patch Patch59: dhcp-dns_client_cancelupdate.patch -Patch60: dhcp-4.2.5-centos-branding.patch +Patch60: dhcp-prepend.patch +Patch61: dhcp-addignore.patch +Patch62: dhcp-max-fd-value.patch BuildRequires: autoconf BuildRequires: automake @@ -388,7 +390,15 @@ rm -rf includes/isc-dhcp # dhclient crashes in dns_client_cancelupdate (#1187856) %patch59 -p1 -b .dns_client_cancelupdate -%patch60 -p1 + +# dhclient refuses to prepend ipv6 nameserver (#1234251) +%patch60 -p1 -b .prepend + +# [FEAT] Add ignore-client-uids option to dhcpd (#1306608) +%patch61 -p1 -b .addignore + +# unclosed TCP connections to OMAPI or failover ports can cause DoS (CVE-2016-2774) +%patch62 -p1 -b .max-fd # Update paths in all man pages for page in client/dhclient.conf.5 client/dhclient.leases.5 \ @@ -656,8 +666,23 @@ done %changelog -* Thu Nov 19 2015 CentOS Sources - 4.2.5-42.el7.centos -- Roll in CentOS Branding +* Tue Aug 09 2016 Jiri Popelka - 12:4.2.5-47 +- 1269596 - fix undefined variable in dhclient-script + +* Thu Apr 21 2016 Jiri Popelka - 12:4.2.5-46 +- unclosed TCP connections to OMAPI or failover ports can cause DoS (CVE-2016-2774) + +* Mon Apr 18 2016 Zdenek Dohnal - 12:4.2.5-45 +- 1267489 - dhclient-script does not respect DEFROUTE/GATEWAYDEV patched + +* Mon Apr 18 2016 Zdenek Dohnal - 12:4.2.5-44 +- 1269596 - dhclient-script doesn't keep old nameservers +- 1193586 - DHCP renewal does not update lifetimes if MTU has changed +- 1306608 - Add ignore-client-uids option to dhcpd +- 1267489 - dhclient-script does not respect DEFROUTE/GATEWAYDEV + +* Mon Apr 18 2016 Zdenek Dohnal - 12:4.2.5-43 +- Fixing bug 1234251 * Tue Oct 13 2015 Jiri Popelka - 12:4.2.5-42 - regenerate dhcp-vlanfilter.patch (#1175350)