Hello community,

here is the log from the commit of package dhcpcd for openSUSE:11.4
checked in at Mon Apr 11 16:01:51 CEST 2011.



--------
--- old-versions/11.4/all/dhcpcd/dhcpcd.changes 2010-11-30 15:12:50.000000000 
+0100
+++ 11.4/dhcpcd/dhcpcd.changes  2011-04-06 21:19:43.000000000 +0200
@@ -1,0 +2,18 @@
+Wed Apr  6 15:05:57 UTC 2011 - m...@suse.de
+
+- Relaxed the check of the domain-name option causing a regression,
+  when the server is misusing it to provide a domain list and does
+  not provide it using the domain-search option (bnc#675052).
+
+-------------------------------------------------------------------
+Wed Mar 30 10:16:31 UTC 2011 - m...@suse.de
+
+- bnc#675052 - discard string options such as host and domain names
+  containing disallowed characters or beeing too long. This proctive
+  patch limits root-path to a-zA-Z0-9, #%+-_:.,@~/\[]= and a space
+  (CVE-2011-0996).
+- fixed to read netbios scope from info file as string
+- bnc#668194 - handle packets with xen partial UDP checksums
+- bnc#657402 - send renew messages as unicast directly to the server
+
+-------------------------------------------------------------------

Package does not exist at destination yet. Using Fallback 
old-versions/11.4/all/dhcpcd
Destination is old-versions/11.4/UPDATES/all/dhcpcd
calling whatdependson for 11.4-i586


New:
----
  dhcpcd-3.2.3-option-checks.diff
  dhcpcd-3.2.3-renew-unicast.diff
  dhcpcd-3.2.3-xen-checksum.diff

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ dhcpcd.spec ++++++
--- /var/tmp/diff_new_pack.LLkpyC/_old  2011-04-11 16:01:34.000000000 +0200
+++ /var/tmp/diff_new_pack.LLkpyC/_new  2011-04-11 16:01:34.000000000 +0200
@@ -1,7 +1,7 @@
 #
-# spec file for package dhcpcd (Version 3.2.3)
+# spec file for package dhcpcd
 #
-# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 
 Name:           dhcpcd
 Version:        3.2.3
-Release:        63
+Release:        66.<RELEASE67>
 Summary:        A DHCP Client Daemon
 Url:            http://developer.berlios.de/projects/dhcpcd/
 #Source:       http://prdownload.berlios.de/dhcpcd/dhcpcd-3.2.3.tar.bz2
@@ -46,6 +46,9 @@
 Patch17:        bnc#564441.diff
 Patch18:        bnc#577402.diff
 Patch19:        bnc#579438.diff
+Patch20:        dhcpcd-3.2.3-renew-unicast.diff
+Patch21:        dhcpcd-3.2.3-xen-checksum.diff
+Patch22:        dhcpcd-3.2.3-option-checks.diff
 License:        GPLv2+
 Group:          Productivity/Networking/Boot/Clients
 Provides:       dhcp_client
@@ -87,6 +90,9 @@
 %patch17 -p0
 %patch18 -p0
 %patch19 -p0
+%patch20 -p0
+%patch21 -p0
+%patch22 -p0
 cp %{S:1} .
 cp %{S:3} .
 

++++++ dhcpcd-3.2.3-more-params.diff ++++++
--- /var/tmp/diff_new_pack.LLkpyC/_old  2011-04-11 16:01:35.000000000 +0200
+++ /var/tmp/diff_new_pack.LLkpyC/_new  2011-04-11 16:01:35.000000000 +0200
@@ -186,7 +186,7 @@
 +              else if (strcmp (var, "LOGSERVER") == 0)
 +                      dhcp->logservers = parse_addresses (value, "LOGSERVER");
 +              else if (strcmp (var, "NETBIOSSCOPE") == 0)
-+                      parse_uint (&dhcp->netbiosscope, value, "NETBIOSSCOPE");
++                      dhcp->netbiosscope = xstrdup (value);
 +              else if (strcmp (var, "NETBIOSNAMESERVER") == 0)
 +                      dhcp->netbiosnameservers = parse_addresses (value, 
"NETBIOSNAMESERVER");
 +              else if (strcmp (var, "NETBIOSDDSERVER") == 0)

++++++ dhcpcd-3.2.3-option-checks.diff ++++++
--- configure.c
+++ configure.c
@@ -540,7 +540,7 @@ static char *lookuphostname (char *hostname, const dhcp_t 
*dhcp,
        char *addr;
        struct addrinfo hints;
        struct addrinfo *res = NULL;
-       int result;
+       int result, check;
 
        logger (LOG_DEBUG, "Looking up hostname via DNS");
        addr = xmalloc (sizeof (char) * NI_MAXHOST);
@@ -565,9 +565,10 @@ static char *lookuphostname (char *hostname, const dhcp_t 
*dhcp,
        result = getaddrinfo (addr, "0", &hints, &res);
        if (res)
                freeaddrinfo (res);
-       if (result == 0)
+       check = check_domain_name(addr, strlen(addr), 0);
+       if (result == 0 || check != 0)
                logger (LOG_ERR, "malicious PTR record detected");
-       if (result == 0 || ! *addr) {
+       if (result == 0 || ! *addr || check != 0) {
                free (addr);
                return (NULL);
        }
@@ -842,12 +843,12 @@ int configure (const options_t *options, interface_t 
*iface,
                exec_script (options->script, iface->infofile, "up");
 
        curhostname = xmalloc (sizeof (char) * MAXHOSTNAMELEN);
-       *curhostname = '\0';
+       memset(curhostname, 0, MAXHOSTNAMELEN);
 
-       gethostname (curhostname, MAXHOSTNAMELEN);
+       gethostname (curhostname, MAXHOSTNAMELEN - 1);
+       curhostname[MAXHOSTNAMELEN - 1] = '\0';
        if (options->dohostname ||
-           strlen (curhostname) == 0 ||
-           strcmp (curhostname, "(none)") == 0 ||
+           check_domain_name(curhostname, strlen (curhostname), 0) != 0 ||
            strcmp (curhostname, "localhost") == 0)
        {
                newhostname = xmalloc (sizeof (char) * MAXHOSTNAMELEN);
--- dhcp.c
+++ dhcp.c
@@ -41,6 +41,8 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stddef.h>
+#include <ctype.h>
 
 #include "config.h"
 
@@ -316,6 +318,7 @@ ssize_t send_message (const interface_t *iface, const 
dhcp_t *dhcp,
                        *p++ = DHCP_LOGSERVER;
                        *p++ = DHCP_NETBIOSNAMESERVER;
                        *p++ = DHCP_NETBIOSDDSERVER;
+                       *p++ = DHCP_NETBIOSNODETYPE;
                        *p++ = DHCP_NETBIOSSCOPE;
                }
 
@@ -646,6 +649,106 @@ static struct route_head *decode_routers (const unsigned 
char *data, int length)
        return (head);
 }
 
+int check_domain_name(const char *ptr, size_t len, int dots)
+{
+       const char *p;
+
+       /* not empty or complete length not over 255 characters   */
+       if (len == 0 || len >= 256)
+               return -1;
+
+       /* consists of [[:alnum:]-]+ labels separated by [.]      */
+       /* a [_] is against RFC but seems to be "widely used"...  */
+       for (p=ptr; *p && len-- > 0; p++) {
+               if ( *p == '-' || *p == '_') {
+                       /* not allowed at begin or end of a label */
+                       if ((p - ptr) == 0 || len == 0 || p[1] == '.')
+                               return -1;
+               } else
+               if ( *p == '.') {
+                       /* each label has to be 1-63 characters;
+                          we allow [.] at the end ('foo.bar.')   */
+                       ptrdiff_t d = p - ptr;
+                       if( d <= 0 || d >= 64)
+                               return -1;
+                       ptr = p + 1; /* jump to the next label    */
+                       if(dots > 0 && len > 0)
+                               dots--;
+               } else
+               if ( !isalnum((unsigned char)*p)) {
+                       /* also numbers at the begin are fine     */
+                       return -1;
+               }
+       }
+       return dots ? -1 : 0;
+}
+
+int check_domain_name_list(const char *ptr, size_t len, int dots)
+{
+       const char *p;
+       int ret = -1; /* at least one needed */
+
+       if (!ptr || !len)
+               return -1;
+
+       for (p=ptr; *p && len > 0; p++, len--) {
+               if (*p != ' ')
+                       continue;
+               if (p > ptr) {
+                       if (check_domain_name(ptr, p - ptr, dots) != 0)
+                               return -1;
+                       ret = 0;
+               }
+               ptr = p + 1;
+       }
+       if (p > ptr)
+               return check_domain_name(ptr, p - ptr, dots);
+       else
+               return ret;
+}
+
+int check_dhcp_option(unsigned char option, const char *ptr, size_t len)
+{
+       if( !ptr)
+               return -1;
+
+       switch (option) {
+               case DHCP_NETBIOSNODETYPE:
+                       if(len == 1 && ((int)*ptr == 1 || (int)*ptr == 2 ||
+                                       (int)*ptr == 4 || (int)*ptr == 8))
+                               return 0;
+               break;
+               case DHCP_HOSTNAME:
+               case DHCP_NISDOMAIN:
+               case DHCP_NETBIOSSCOPE:
+                       return check_domain_name(ptr, len, 0);
+               break;
+               case DHCP_SIPSERVER:
+               case DHCP_DNSDOMAIN: /* accept a list for compatibiliy */
+               case DHCP_DNSSEARCH:
+                       return check_domain_name_list(ptr, len, 0);
+               break;
+               case DHCP_ROOTPATH:
+                       if( len == 0)
+                               return -1;
+                       for (; *ptr && len-- > 0; ptr++) {
+                               if( !(isalnum((unsigned char)*ptr) ||
+                                       *ptr == '#'  || *ptr == '%' ||
+                                       *ptr == '+'  || *ptr == '-' ||
+                                       *ptr == '_'  || *ptr == ':' ||
+                                       *ptr == '.'  || *ptr == ',' ||
+                                       *ptr == '@'  || *ptr == '~' ||
+                                       *ptr == '\\' || *ptr == '/' ||
+                                       *ptr == '['  || *ptr == ']' ||
+                                       *ptr == '='  || *ptr == ' '))
+                                       return -1;
+                       }
+                       return 0;
+               break;
+       }
+       return 0;
+}
+
 int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message)
 {
        const unsigned char *p = message->options;
@@ -676,8 +779,16 @@ int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t 
*message)
        dhcp->leasedfrom = tv.tv_sec;
        dhcp->frominfo = false;
        dhcp->address.s_addr = message->yiaddr;
-       strlcpy (dhcp->servername, (char *) message->servername,
-                sizeof (dhcp->servername));
+       if (message->servername[0] != '\0' &&
+               check_domain_name((const char *)message->servername,
+                       strlen((const char *)message->servername), 0) != 0)
+       {
+               logger (LOG_ERR, "suspect value in SERVERNAME - discarded");
+               dhcp->servername[0] = '\0';
+       } else {
+               strlcpy (dhcp->servername, (char *) message->servername,
+                        sizeof (dhcp->servername));
+       }
 
 #define LEN_ERR \
        { \
@@ -798,10 +909,20 @@ parse_start:
        memcpy (_var, p, (size_t) length); \
        memset (_var + length, 0, 1); \
 }
+#define CHECKOPT(_opt,_var) \
+       if(check_dhcp_option(_opt, (const char *)p, length) != 0) { \
+               logger (LOG_ERR, "suspect value in option %s - discarded", 
#_opt); \
+               if (_var) free (_var); \
+               _var = NULL; \
+       }
                        case DHCP_HOSTNAME:
+                               CHECKOPT (DHCP_HOSTNAME, dhcp->hostname)
+                               else
                                GETSTR (dhcp->hostname);
                                break;
                        case DHCP_DNSDOMAIN:
+                               CHECKOPT (DHCP_DNSDOMAIN, dhcp->dnsdomain)
+                               else
                                GETSTR (dhcp->dnsdomain);
                                break;
                        case DHCP_MESSAGE:
@@ -809,18 +930,30 @@ parse_start:
                                break;
 #ifdef ENABLE_INFO
                        case DHCP_ROOTPATH:
+                               CHECKOPT (DHCP_ROOTPATH, dhcp->rootpath)
+                               else
                                GETSTR (dhcp->rootpath);
                                break;
 #endif
 #ifdef ENABLE_NIS
                        case DHCP_NISDOMAIN:
+                               CHECKOPT (DHCP_NISDOMAIN, dhcp->nisdomain)
+                               else
                                GETSTR (dhcp->nisdomain);
                                break;
 #endif
                        case DHCP_NETBIOSNODETYPE:
-                               GETSTR (dhcp->netbiosnodetype);
+                               CHECKOPT (DHCP_NETBIOSNODETYPE, 
dhcp->netbiosnodetype)
+                               else {
+                                       if(dhcp->netbiosnodetype)
+                                               free(dhcp->netbiosnodetype);
+                                       dhcp->netbiosnodetype = xmalloc 
((size_t)length + 1);
+                                       snprintf(dhcp->netbiosnodetype, length 
+ 1, "%d", (int)*p);
+                               }
                                break;
                        case DHCP_NETBIOSSCOPE:
+                               CHECKOPT (DHCP_NETBIOSSCOPE, dhcp->netbiosscope)
+                               else
                                GETSTR (dhcp->netbiosscope);
                                break;
 
@@ -863,11 +996,21 @@ parse_start:
                        case DHCP_DNSSEARCH:
                                MIN_LENGTH (1);
                                free (dhcp->dnssearch);
+                               dhcp->dnssearch = NULL;
                                len = decode_search (p, length, NULL);
                                if (len > 0) {
-                                       dhcp->dnssearch = xmalloc (len);
-                                       decode_search (p, length,
-                                                      dhcp->dnssearch);
+                                       char *str = xmalloc (len);
+                                       decode_search (p, length, str);
+                                       if (check_dhcp_option(DHCP_DNSSEARCH,
+                                               str, len - 1) != 0) {
+                                               logger (LOG_ERR,
+                                                       "suspect value in "
+                                                       "option %s - discarded",
+                                                       "DHCP_DNSSEARCH");
+                                               free(str);
+                                       } else {
+                                               dhcp->dnssearch = str;
+                                       }
                                }
                                break;
 
@@ -885,8 +1028,22 @@ parse_start:
 
 #ifdef ENABLE_INFO
                        case DHCP_SIPSERVER:
-                               free (dhcp->sipservers);
-                               dhcp->sipservers = decode_sipservers (p,length);
+                               if(dhcp->sipservers)
+                                       free (dhcp->sipservers);
+                               dhcp->sipservers = NULL;
+                               {
+                                       char *str = decode_sipservers 
(p,length);
+                                       if(check_dhcp_option(DHCP_SIPSERVER,
+                                               str, strlen(str)) != 0) {
+                                               logger (LOG_ERR,
+                                                       "suspect value in "
+                                                       "option %s - discarded",
+                                                       "DHCP_SIPSERVER");
+                                               free(str);
+                                       } else {
+                                               dhcp->sipservers = str;
+                                       }
+                               }
                                break;
 #endif
 
@@ -922,6 +1079,7 @@ parse_start:
 #undef LENGTH
 #undef MIN_LENGTH
 #undef MULT_LENGTH
+#undef CHECKOPT
 
                        default:
                                logger (LOG_DEBUG,
--- dhcp.h
+++ dhcp.h
@@ -252,4 +252,8 @@ ssize_t send_message (const interface_t *iface, const 
dhcp_t *dhcp,
 void free_dhcp (dhcp_t *dhcp);
 int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message);
 
+int check_dhcp_option(unsigned char option, const char *ptr, size_t len);
+int check_domain_name(const char *ptr, size_t len, int dots);
+int check_domain_name_list(const char *ptr, size_t len, int dots);
+
 #endif
--- dhcpcd.c
+++ dhcpcd.c
@@ -182,8 +182,10 @@ int main(int argc, char **argv)
        options->netconfig = false;
        options->timeout = DEFAULT_TIMEOUT;
 
-       gethostname (options->hostname, sizeof (options->hostname));
-       if (strcmp (options->hostname, "(none)") == 0 ||
+       memset (options->hostname, 0, sizeof (options->hostname));
+       gethostname (options->hostname, sizeof (options->hostname) - 1);
+       options->hostname[sizeof (options->hostname) - 1] = '\0';
+       if (check_domain_name(options->hostname, strlen(options->hostname), 0) 
!= 0 ||
            strcmp (options->hostname, "localhost") == 0)
                memset (options->hostname, 0, sizeof (options->hostname));
 
@@ -232,6 +234,9 @@ int main(int argc, char **argv)
                                                "`%s' too long for HostName 
string, max is %d",
                                                optarg, MAXHOSTNAMELEN);
                                        goto abort;
+                               } else if(check_domain_name(optarg, 
strlen(optarg), 0) != 0) {
+                                       logger (LOG_ERR, "suspect string in 
hostname argument");
+                                       goto abort;
                                } else
                                        strlcpy (options->hostname, optarg,
                                                 sizeof (options->hostname));
++++++ dhcpcd-3.2.3-renew-unicast.diff ++++++
--- dhcp.c
+++ dhcp.c
@@ -333,6 +333,22 @@ ssize_t send_message (const interface_t *iface, const 
dhcp_t *dhcp,
 
        message_length = p - m;
 
+       if (to.s_addr && to.s_addr != INADDR_BROADCAST) {
+               struct sockaddr_in sin_to;
+
+               memset(&sin_to, 0, sizeof(sin_to));
+               sin_to.sin_family = AF_INET;
+               sin_to.sin_addr.s_addr = to.s_addr;
+               sin_to.sin_port = htons(DHCP_SERVER_PORT);
+
+               logger (LOG_DEBUG, "sending %s with xid 0x%x to %s",
+                       dhcp_message (type), xid, inet_ntoa(to));
+
+               return sendto(iface->listen_fd,
+                               (unsigned char *) message, message_length,
+                               0, (struct sockaddr *)&sin_to, sizeof(sin_to));
+       }
+
        packet = xzalloc (sizeof (*packet));
        make_dhcp_packet (packet, (unsigned char *) message, message_length,
                          from, to);
@@ -340,6 +356,7 @@ ssize_t send_message (const interface_t *iface, const 
dhcp_t *dhcp,
 
        logger (LOG_DEBUG, "sending %s with xid 0x%x",
                dhcp_message (type), xid);
+
        retval = send_packet (iface, ETHERTYPE_IP, (unsigned char *) packet,
                              message_length +
                              sizeof (packet->ip) + sizeof (packet->udp));
--- socket.c
+++ socket.c
@@ -461,8 +461,8 @@ int open_socket (interface_t *iface, int protocol)
 
        /* We need to bind to a port, otherwise Linux generate ICMP messages
         * that cannot contect the port when we have an address.
-        * We don't actually use this fd at all, instead using our packet
-        * filter socket. */
+        * We actually use this fd for unicast messages only, otherwise we're
+        * using our packet filter socket. So read it as udp_fd ... */
        if (iface->listen_fd == -1 && protocol == ETHERTYPE_IP) {
                if ((fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
                        logger (LOG_ERR, "socket: %s", strerror (errno));
++++++ dhcpcd-3.2.3-xen-checksum.diff ++++++
--- socket.c
+++ socket.c
@@ -48,7 +48,8 @@
 # include <net/bpf.h>
 #elif __linux__
 # include <linux/filter.h>
-# include <netpacket/packet.h>
+# include <linux/if_packet.h>
+/* # include <netpacket/packet.h> */
 # define bpf_insn sock_filter
 #endif
 
@@ -202,7 +203,7 @@ void make_dhcp_packet(struct udp_dhcp_packet *packet,
        ip->ip_sum = checksum ((unsigned char *) ip, sizeof (*ip));
 }
 
-static int valid_dhcp_packet (unsigned char *data)
+static int valid_dhcp_packet (unsigned char *data, int nocsum)
 {
        union
        {
@@ -242,7 +243,7 @@ static int valid_dhcp_packet (unsigned char *data)
        memcpy (&d.packet->ip.ip_src, &source, sizeof (d.packet->ip.ip_src));
        memcpy (&d.packet->ip.ip_dst, &dest, sizeof (d.packet->ip.ip_dst));
        d.packet->ip.ip_len = d.packet->udp.uh_ulen;
-       if (udpsum && udpsum != checksum (d.data, bytes)) {
+       if (!nocsum && udpsum && udpsum != checksum (d.data, bytes)) {
                logger (LOG_ERR, "bad UDP checksum, ignoring");
                retval = -1;
        }
@@ -409,7 +410,7 @@ ssize_t get_packet (const interface_t *iface, unsigned char 
*data,
                        memcpy (data, payload, len);
                        have_data = true;
                } else {
-                       if (valid_dhcp_packet (payload) >= 0) {
+                       if (valid_dhcp_packet (payload, 0) >= 0) {
                                union
                                {
                                        unsigned char *buffer;
@@ -535,6 +536,16 @@ int open_socket (interface_t *iface, int protocol)
                return (-1);
        }
 
+       n = 1;
+       if (setsockopt (fd, SOL_PACKET, PACKET_AUXDATA, &n, sizeof(n)) < 0) {
+               if (errno != ENOPROTOOPT) {
+                       logger (LOG_ERR, "failed to set auxiliary packet data: 
%s",
+                               strerror (errno));
+                       close (fd);
+                       return (-1);
+               }
+       }
+
        if (iface->fd > -1)
                close (iface->fd);
        iface->fd = fd;
@@ -594,13 +605,26 @@ ssize_t get_packet (const interface_t *iface, unsigned 
char *data,
                unsigned char *buffer;
                struct udp_dhcp_packet *packet;
        } pay;
+       unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
+       struct iovec iov = {
+               .iov_base = buffer,
+               .iov_len  = iface->buffer_length,
+       };
+       struct msghdr msg = {
+               .msg_iov = &iov,
+               .msg_iovlen = 1,
+               .msg_control = cmsgbuf,
+               .msg_controllen = sizeof(cmsgbuf),
+       };
+       struct cmsghdr *cmsg;
+       int nocsum = 0;
 
        /* We don't use the given buffer, but we need to rewind the position */
        *buffer_pos = 0;
 
        memset (buffer, 0, iface->buffer_length);
-       bytes = read (iface->fd, buffer, iface->buffer_length);
 
+       bytes = recvmsg (iface->fd, &msg, 0);
        if (bytes == -1) {
                struct timespec ts;
                logger (LOG_ERR, "read: %s", strerror (errno));
@@ -609,6 +633,13 @@ ssize_t get_packet (const interface_t *iface, unsigned 
char *data,
                nanosleep (&ts, NULL);
                return (-1);
        }
+       for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+               if (cmsg->cmsg_level == SOL_PACKET &&
+                   cmsg->cmsg_type == PACKET_AUXDATA) {
+                       struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
+                       nocsum = aux->tp_status & TP_STATUS_CSUMNOTREADY;
+               }
+       }
 
        *buffer_len = bytes;
        /* If it's an ARP reply, then just send it back */
@@ -630,7 +661,7 @@ ssize_t get_packet (const interface_t *iface, unsigned char 
*data,
                return (-1);
        }
 
-       if (valid_dhcp_packet (buffer) == -1)
+       if (valid_dhcp_packet (buffer, nocsum) == -1)
                return (-1);
 
        bytes = ntohs (pay.packet->ip.ip_len) -

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



Remember to have fun...

-- 
To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org
For additional commands, e-mail: opensuse-commit+h...@opensuse.org

Reply via email to