~ubuntu-branches/ubuntu/quantal/sudo/quantal

« back to all changes in this revision

Viewing changes to .pc/CVE-2012-2337.patch/plugins/sudoers/match_addr.c

  • Committer: Package Import Robot
  • Author(s): Tyler Hicks
  • Date: 2012-05-16 09:42:17 UTC
  • Revision ID: package-import@ubuntu.com-20120516094217-x9gto7y6hhflwl9v
Tags: 1.8.3p1-1ubuntu5
* SECURITY UPDATE: Properly handle netmasks in sudoers Host and Host_List
  values (LP: #1000276)
  - debian/patches/CVE-2012-2337.patch: Don't perform IPv6 checks on IPv4
    addresses. Based on upstream patch.
  - CVE-2012-2337

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1996, 1998-2005, 2007-2011
 
3
 *      Todd C. Miller <Todd.Miller@courtesan.com>
 
4
 *
 
5
 * Permission to use, copy, modify, and distribute this software for any
 
6
 * purpose with or without fee is hereby granted, provided that the above
 
7
 * copyright notice and this permission notice appear in all copies.
 
8
 *
 
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
16
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
17
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
18
 *
 
19
 * Sponsored in part by the Defense Advanced Research Projects
 
20
 * Agency (DARPA) and Air Force Research Laboratory, Air Force
 
21
 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
 
22
 */
 
23
 
 
24
#include <config.h>
 
25
 
 
26
#include <sys/types.h>
 
27
#include <sys/socket.h>
 
28
#include <stdio.h>
 
29
#ifdef STDC_HEADERS
 
30
# include <stdlib.h>
 
31
# include <stddef.h>
 
32
#else
 
33
# ifdef HAVE_STDLIB_H
 
34
#  include <stdlib.h>
 
35
# endif
 
36
#endif /* STDC_HEADERS */
 
37
#ifdef HAVE_STRING_H
 
38
# include <string.h>
 
39
#endif /* HAVE_STRING_H */
 
40
#ifdef HAVE_STRINGS_H
 
41
# include <strings.h>
 
42
#endif /* HAVE_STRINGS_H */
 
43
#ifdef HAVE_UNISTD_H
 
44
# include <unistd.h>
 
45
#endif /* HAVE_UNISTD_H */
 
46
#include <netinet/in.h>
 
47
#include <arpa/inet.h>
 
48
#include <netdb.h>
 
49
 
 
50
#include "sudoers.h"
 
51
#include "interfaces.h"
 
52
 
 
53
static int
 
54
addr_matches_if(char *n)
 
55
{
 
56
    union sudo_in_addr_un addr;
 
57
    struct interface *ifp;
 
58
#ifdef HAVE_IN6_ADDR
 
59
    int j;
 
60
#endif
 
61
    int family;
 
62
 
 
63
#ifdef HAVE_IN6_ADDR
 
64
    if (inet_pton(AF_INET6, n, &addr.ip6) > 0) {
 
65
        family = AF_INET6;
 
66
    } else
 
67
#endif
 
68
    {
 
69
        family = AF_INET;
 
70
        addr.ip4.s_addr = inet_addr(n);
 
71
    }
 
72
 
 
73
    for (ifp = interfaces; ifp != NULL; ifp = ifp->next) {
 
74
        if (ifp->family != family)
 
75
            continue;
 
76
        switch(family) {
 
77
            case AF_INET:
 
78
                if (ifp->addr.ip4.s_addr == addr.ip4.s_addr ||
 
79
                    (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr)
 
80
                    == addr.ip4.s_addr)
 
81
                    return TRUE;
 
82
                break;
 
83
#ifdef HAVE_IN6_ADDR
 
84
            case AF_INET6:
 
85
                if (memcmp(ifp->addr.ip6.s6_addr, addr.ip6.s6_addr,
 
86
                    sizeof(addr.ip6.s6_addr)) == 0)
 
87
                    return TRUE;
 
88
                for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
 
89
                    if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
 
90
                        break;
 
91
                }
 
92
                if (j == sizeof(addr.ip6.s6_addr))
 
93
                    return TRUE;
 
94
#endif
 
95
        }
 
96
    }
 
97
 
 
98
    return FALSE;
 
99
}
 
100
 
 
101
static int
 
102
addr_matches_if_netmask(char *n, char *m)
 
103
{
 
104
    int i;
 
105
    union sudo_in_addr_un addr, mask;
 
106
    struct interface *ifp;
 
107
#ifdef HAVE_IN6_ADDR
 
108
    int j;
 
109
#endif
 
110
    int family;
 
111
 
 
112
#ifdef HAVE_IN6_ADDR
 
113
    if (inet_pton(AF_INET6, n, &addr.ip6) > 0)
 
114
        family = AF_INET6;
 
115
    else
 
116
#endif
 
117
    {
 
118
        family = AF_INET;
 
119
        addr.ip4.s_addr = inet_addr(n);
 
120
    }
 
121
 
 
122
    if (family == AF_INET) {
 
123
        if (strchr(m, '.')) {
 
124
            mask.ip4.s_addr = inet_addr(m);
 
125
        } else {
 
126
            i = atoi(m);
 
127
            if (i == 0)
 
128
                mask.ip4.s_addr = 0;
 
129
            else if (i == 32)
 
130
                mask.ip4.s_addr = 0xffffffff;
 
131
            else
 
132
                mask.ip4.s_addr = 0xffffffff - (1 << (32 - i)) + 1;
 
133
            mask.ip4.s_addr = htonl(mask.ip4.s_addr);
 
134
        }
 
135
        addr.ip4.s_addr &= mask.ip4.s_addr;
 
136
    }
 
137
#ifdef HAVE_IN6_ADDR
 
138
    else {
 
139
        if (inet_pton(AF_INET6, m, &mask.ip6) <= 0) {
 
140
            j = atoi(m);
 
141
            for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) {
 
142
                if (j < i * 8)
 
143
                    mask.ip6.s6_addr[i] = 0;
 
144
                else if (i * 8 + 8 <= j)
 
145
                    mask.ip6.s6_addr[i] = 0xff;
 
146
                else
 
147
                    mask.ip6.s6_addr[i] = 0xff00 >> (j - i * 8);
 
148
                addr.ip6.s6_addr[i] &= mask.ip6.s6_addr[i];
 
149
            }
 
150
        }
 
151
    }
 
152
#endif /* HAVE_IN6_ADDR */
 
153
 
 
154
    for (ifp = interfaces; ifp != NULL; ifp = ifp->next) {
 
155
        if (ifp->family != family)
 
156
            continue;
 
157
        switch(family) {
 
158
            case AF_INET:
 
159
                if ((ifp->addr.ip4.s_addr & mask.ip4.s_addr) == addr.ip4.s_addr)
 
160
                    return TRUE;
 
161
#ifdef HAVE_IN6_ADDR
 
162
            case AF_INET6:
 
163
                for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
 
164
                    if ((ifp->addr.ip6.s6_addr[j] & mask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
 
165
                        break;
 
166
                }
 
167
                if (j == sizeof(addr.ip6.s6_addr))
 
168
                    return TRUE;
 
169
#endif /* HAVE_IN6_ADDR */
 
170
        }
 
171
    }
 
172
 
 
173
    return FALSE;
 
174
}
 
175
 
 
176
/*
 
177
 * Returns TRUE if "n" is one of our ip addresses or if
 
178
 * "n" is a network that we are on, else returns FALSE.
 
179
 */
 
180
int
 
181
addr_matches(char *n)
 
182
{
 
183
    char *m;
 
184
    int retval;
 
185
 
 
186
    /* If there's an explicit netmask, use it. */
 
187
    if ((m = strchr(n, '/'))) {
 
188
        *m++ = '\0';
 
189
        retval = addr_matches_if_netmask(n, m);
 
190
        *(m - 1) = '/';
 
191
    } else
 
192
        retval = addr_matches_if(n);
 
193
 
 
194
    return retval;
 
195
}