~d-jj/+junk/sudo

« back to all changes in this revision

Viewing changes to src/net_ifs.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2015-05-13 15:43:49 UTC
  • mfrom: (1.4.17) (1.3.38 sid)
  • Revision ID: package-import@ubuntu.com-20150513154349-3wazxyt6jxlgtgpi
Tags: 1.8.12-1ubuntu1
* Merge from Debian unstable. (LP: #1451274, LP: #1219337)
  Remaining changes:
  - debian/rules:
    + compile with --without-lecture --with-tty-tickets --enable-admin-flag
    + install man/man8/sudo_root.8 in both flavours
    + install apport hooks
  - debian/sudoers:
    + also grant admin group sudo access
  - debian/source_sudo.py, debian/sudo-ldap.dirs, debian/sudo.dirs:
    + add usr/share/apport/package-hooks
  - debian/sudo.pam:
    + Use pam_env to read /etc/environment and /etc/default/locale
      environment files. Reading ~/.pam_environment is not permitted due to
      security reasons.
  - debian/control:
    + dh-autoreconf dependency fixes missing-build-dependency-for-dh_-command
  - Remaining patches:
    + keep_home_by_default.patch: Keep HOME in the default environment
    + debian/patches/also_check_sudo_group.diff: also check the sudo group
      in plugins/sudoers/sudoers.c to create the admin flag file. Leave the
      admin group check for backwards compatibility.
* Dropped patches no longer needed:
    + add_probe_interfaces_setting.diff
    + actually-use-buildflags.diff
    + CVE-2014-9680.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (c) 1996, 1998-2005, 2007-2014
 
2
 * Copyright (c) 1996, 1998-2005, 2007-2015
3
3
 *      Todd C. Miller <Todd.Miller@courtesan.com>
4
4
 *
5
5
 * Permission to use, copy, modify, and distribute this software for any
84
84
# include <ifaddrs.h>
85
85
#endif
86
86
 
87
 
#include "missing.h"
88
 
#include "alloc.h"
89
 
#include "fatal.h"
 
87
#define _SUDO_NET_IFS_C         /* to expose sudo_inet_ntop in sudo_compat.h */
 
88
 
 
89
#define DEFAULT_TEXT_DOMAIN     "sudo"
 
90
#include "sudo_gettext.h"       /* must be included before sudo_compat.h */
 
91
 
 
92
#include "sudo_compat.h"
 
93
#include "sudo_alloc.h"
 
94
#include "sudo_fatal.h"
90
95
#include "sudo_conf.h"
91
96
#include "sudo_debug.h"
92
97
 
93
 
#define DEFAULT_TEXT_DOMAIN     "sudo"
94
 
#include "gettext.h"
95
 
 
96
98
/* Minix apparently lacks IFF_LOOPBACK */
97
99
#ifndef IFF_LOOPBACK
98
100
# define IFF_LOOPBACK   0
99
101
#endif
100
102
 
 
103
#ifndef INET_ADDRSTRLEN
 
104
# define INET_ADDRSTRLEN 16
 
105
#endif
101
106
#ifndef INET6_ADDRSTRLEN
102
107
# define INET6_ADDRSTRLEN 46
103
108
#endif
115
120
    struct sockaddr_in *sin;
116
121
#ifdef HAVE_STRUCT_IN6_ADDR
117
122
    struct sockaddr_in6 *sin6;
118
 
    char addrbuf[INET6_ADDRSTRLEN];
 
123
    char addrstr[INET6_ADDRSTRLEN], maskstr[INET6_ADDRSTRLEN];
 
124
#else
 
125
    char addrstr[INET_ADDRSTRLEN], maskstr[INET_ADDRSTRLEN];
119
126
#endif
120
127
    int ailen, len, num_interfaces = 0;
121
128
    char *cp;
143
150
    if (num_interfaces == 0)
144
151
        debug_return_int(0);
145
152
    ailen = num_interfaces * 2 * INET6_ADDRSTRLEN;
146
 
    *addrinfo = cp = emalloc(ailen);
 
153
    *addrinfo = cp = sudo_emalloc(ailen);
147
154
 
148
155
    /* Store the IP addr/netmask pairs. */
149
156
    for (ifa = ifaddrs; ifa != NULL; ifa = ifa -> ifa_next) {
155
162
        switch (ifa->ifa_addr->sa_family) {
156
163
            case AF_INET:
157
164
                sin = (struct sockaddr_in *)ifa->ifa_addr;
158
 
                len = snprintf(cp, ailen - (*addrinfo - cp),
159
 
                    "%s%s/", cp == *addrinfo ? "" : " ",
160
 
                    inet_ntoa(sin->sin_addr));
161
 
                if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
162
 
                    warningx(U_("load_interfaces: overflow detected"));
163
 
                    goto done;
164
 
                }
165
 
                cp += len;
166
 
 
 
165
                if (inet_ntop(AF_INET, &sin->sin_addr, addrstr, sizeof(addrstr)) == NULL)
 
166
                    continue;
167
167
                sin = (struct sockaddr_in *)ifa->ifa_netmask;
 
168
                if (inet_ntop(AF_INET, &sin->sin_addr, maskstr, sizeof(maskstr)) == NULL)
 
169
                    continue;
 
170
 
168
171
                len = snprintf(cp, ailen - (*addrinfo - cp),
169
 
                    "%s", inet_ntoa(sin->sin_addr));
 
172
                    "%s%s/%s", cp == *addrinfo ? "" : " ", addrstr, maskstr);
170
173
                if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
171
 
                    warningx(U_("load_interfaces: overflow detected"));
 
174
                    sudo_warnx(U_("internal error, %s overflow"), __func__);
172
175
                    goto done;
173
176
                }
174
177
                cp += len;
176
179
#ifdef HAVE_STRUCT_IN6_ADDR
177
180
            case AF_INET6:
178
181
                sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
179
 
                inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, sizeof(addrbuf));
180
 
                len = snprintf(cp, ailen - (*addrinfo - cp),
181
 
                    "%s%s/", cp == *addrinfo ? "" : " ", addrbuf);
182
 
                if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
183
 
                    warningx(U_("load_interfaces: overflow detected"));
184
 
                    goto done;
185
 
                }
186
 
                cp += len;
187
 
 
 
182
                if (inet_ntop(AF_INET6, &sin6->sin6_addr, addrstr, sizeof(addrstr)) == NULL)
 
183
                    continue;
188
184
                sin6 = (struct sockaddr_in6 *)ifa->ifa_netmask;
189
 
                inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, sizeof(addrbuf));
190
 
                len = snprintf(cp, ailen - (*addrinfo - cp), "%s", addrbuf);
 
185
                if (inet_ntop(AF_INET6, &sin6->sin6_addr, maskstr, sizeof(maskstr)) == NULL)
 
186
                    continue;
 
187
 
 
188
                len = snprintf(cp, ailen - (*addrinfo - cp),
 
189
                    "%s%s/%s", cp == *addrinfo ? "" : " ", addrstr, maskstr);
191
190
                if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
192
 
                    warningx(U_("load_interfaces: overflow detected"));
 
191
                    sudo_warnx(U_("internal error, %s overflow"), __func__);
193
192
                    goto done;
194
193
                }
195
194
                cp += len;
202
201
#ifdef HAVE_FREEIFADDRS
203
202
    freeifaddrs(ifaddrs);
204
203
#else
205
 
    efree(ifaddrs);
 
204
    sudo_efree(ifaddrs);
206
205
#endif
207
206
    debug_return_int(num_interfaces);
208
207
}
216
215
int
217
216
get_net_ifs(char **addrinfo)
218
217
{
 
218
    char ifr_tmpbuf[sizeof(struct ifreq)];
 
219
    struct ifreq *ifr, *ifr_tmp = (struct ifreq *)ifr_tmpbuf;
219
220
    struct ifconf *ifconf;
220
 
    struct ifreq *ifr, ifr_tmp;
221
221
    struct sockaddr_in *sin;
222
222
    int ailen, i, len, n, sock, num_interfaces = 0;
223
223
    size_t buflen = sizeof(struct ifconf) + BUFSIZ;
224
224
    char *cp, *previfname = "", *ifconf_buf = NULL;
 
225
    char addrstr[INET_ADDRSTRLEN], maskstr[INET_ADDRSTRLEN];
225
226
#ifdef _ISC
226
227
    struct strioctl strioctl;
227
228
#endif /* _ISC */
232
233
 
233
234
    sock = socket(AF_INET, SOCK_DGRAM, 0);
234
235
    if (sock < 0)
235
 
        fatal(U_("unable to open socket"));
 
236
        sudo_fatal(U_("unable to open socket"));
236
237
 
237
238
    /*
238
239
     * Get interface configuration or return.
239
240
     */
240
241
    for (;;) {
241
 
        ifconf_buf = emalloc(buflen);
 
242
        ifconf_buf = sudo_emalloc(buflen);
242
243
        ifconf = (struct ifconf *) ifconf_buf;
243
244
        ifconf->ifc_len = buflen - sizeof(struct ifconf);
244
245
        ifconf->ifc_buf = (caddr_t) (ifconf_buf + sizeof(struct ifconf));
256
257
        if (ifconf->ifc_len + sizeof(struct ifreq) < buflen)
257
258
            break;
258
259
        buflen += BUFSIZ;
259
 
        efree(ifconf_buf);
 
260
        sudo_efree(ifconf_buf);
260
261
    }
261
262
 
262
263
    /* Allocate space for the maximum number of interfaces that could exist. */
263
264
    if ((n = ifconf->ifc_len / sizeof(struct ifreq)) == 0)
264
265
        debug_return_int(0);
265
266
    ailen = n * 2 * INET6_ADDRSTRLEN;
266
 
    *addrinfo = cp = emalloc(ailen);
 
267
    *addrinfo = cp = sudo_emalloc(ailen);
267
268
 
268
269
    /* For each interface, store the ip address and netmask. */
269
270
    for (i = 0; i < ifconf->ifc_len; ) {
287
288
                continue;
288
289
 
289
290
#ifdef SIOCGIFFLAGS
290
 
        memset(&ifr_tmp, 0, sizeof(ifr_tmp));
291
 
        strncpy(ifr_tmp.ifr_name, ifr->ifr_name, sizeof(ifr_tmp.ifr_name) - 1);
292
 
        if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr_tmp) < 0)
 
291
        memset(ifr_tmp, 0, sizeof(*ifr_tmp));
 
292
        strncpy(ifr_tmp->ifr_name, ifr->ifr_name, sizeof(ifr_tmp->ifr_name) - 1);
 
293
        if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) ifr_tmp) < 0)
293
294
#endif
294
 
            ifr_tmp = *ifr;
 
295
            memcpy(ifr_tmp, ifr, sizeof(*ifr_tmp));
295
296
        
296
297
        /* Skip interfaces marked "down" and "loopback". */
297
 
        if (!ISSET(ifr_tmp.ifr_flags, IFF_UP) ||
298
 
            ISSET(ifr_tmp.ifr_flags, IFF_LOOPBACK))
 
298
        if (!ISSET(ifr_tmp->ifr_flags, IFF_UP) ||
 
299
            ISSET(ifr_tmp->ifr_flags, IFF_LOOPBACK))
299
300
                continue;
300
301
 
 
302
        /* Get the netmask. */
 
303
        memset(ifr_tmp, 0, sizeof(*ifr_tmp));
 
304
        strncpy(ifr_tmp->ifr_name, ifr->ifr_name, sizeof(ifr_tmp->ifr_name) - 1);
 
305
        sin = (struct sockaddr_in *) &ifr_tmp->ifr_addr;
 
306
#ifdef _ISC
 
307
        STRSET(SIOCGIFNETMASK, (caddr_t) ifr_tmp, sizeof(*ifr_tmp));
 
308
        if (ioctl(sock, I_STR, (caddr_t) &strioctl) < 0)
 
309
#else
 
310
        if (ioctl(sock, SIOCGIFNETMASK, (caddr_t) ifr_tmp) < 0)
 
311
#endif /* _ISC */
 
312
            sin->sin_addr.s_addr = htonl(IN_CLASSC_NET);
 
313
 
 
314
        /* Convert the addr and mask to string form. */
301
315
        sin = (struct sockaddr_in *) &ifr->ifr_addr;
 
316
        if (inet_ntop(AF_INET, &sin->sin_addr, addrstr, sizeof(addrstr)) == NULL)
 
317
            continue;
 
318
        sin = (struct sockaddr_in *) &ifr_tmp->ifr_addr;
 
319
        if (inet_ntop(AF_INET, &sin->sin_addr, maskstr, sizeof(maskstr)) == NULL)
 
320
            continue;
 
321
 
302
322
        len = snprintf(cp, ailen - (*addrinfo - cp),
303
 
            "%s%s/", cp == *addrinfo ? "" : " ",
304
 
            inet_ntoa(sin->sin_addr));
 
323
            "%s%s/%s", cp == *addrinfo ? "" : " ", addrstr, maskstr);
305
324
        if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
306
 
            warningx(U_("load_interfaces: overflow detected"));
 
325
            sudo_warnx(U_("internal error, %s overflow"), __func__);
307
326
            goto done;
308
327
        }
309
328
        cp += len;
310
329
 
311
330
        /* Stash the name of the interface we saved. */
312
331
        previfname = ifr->ifr_name;
313
 
 
314
 
        /* Get the netmask. */
315
 
        memset(&ifr_tmp, 0, sizeof(ifr_tmp));
316
 
        strncpy(ifr_tmp.ifr_name, ifr->ifr_name, sizeof(ifr_tmp.ifr_name) - 1);
317
 
#ifdef _ISC
318
 
        STRSET(SIOCGIFNETMASK, (caddr_t) &ifr_tmp, sizeof(ifr_tmp));
319
 
        if (ioctl(sock, I_STR, (caddr_t) &strioctl) < 0) {
320
 
#else
321
 
        if (ioctl(sock, SIOCGIFNETMASK, (caddr_t) &ifr_tmp) < 0) {
322
 
#endif /* _ISC */
323
 
            sin = (struct sockaddr_in *) &ifr_tmp.ifr_addr;
324
 
            sin->sin_addr.s_addr = htonl(IN_CLASSC_NET);
325
 
        }
326
 
        sin = (struct sockaddr_in *) &ifr_tmp.ifr_addr;
327
 
        len = snprintf(cp, ailen - (*addrinfo - cp),
328
 
            "%s", inet_ntoa(sin->sin_addr));
329
 
        if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
330
 
            warningx(U_("load_interfaces: overflow detected"));
331
 
            goto done;
332
 
        }
333
 
        cp += len;
334
332
        num_interfaces++;
335
333
    }
336
334
 
337
335
done:
338
 
    efree(ifconf_buf);
 
336
    sudo_efree(ifconf_buf);
339
337
    (void) close(sock);
340
338
 
341
339
    debug_return_int(num_interfaces);