~ari-tczew/ubuntu/dapper/fetchmail/fix-CVE-2008-2711

« back to all changes in this revision

Viewing changes to checkalias.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2006-02-07 12:12:13 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060207121213-onurwfrzdlzlzxnt
Tags: 6.3.2-2ubuntu1
* Resynchronise with Debian. This brings the new upstream version to dapper
  since upstream support for 6.2 was dropped.
* Drop debian/patches/CVE-2005-4348.dpatch, upstream now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 * For license terms, see the file COPYING in this directory.
6
6
 */
7
7
#include "config.h"
8
 
#ifdef HAVE_GETHOSTBYNAME
9
8
#include <stdlib.h>
10
9
#include <stdio.h>
11
10
#include <string.h>
23
22
#include "i18n.h"
24
23
#include "mx.h"
25
24
#include "fetchmail.h"
 
25
#include "getaddrinfo.h"
26
26
 
27
27
#define MX_RETRIES      3
28
28
 
 
29
typedef unsigned char address_t[sizeof (struct in_addr)];
 
30
 
 
31
static int getaddresses(struct addrinfo **result, const char *name)
 
32
{
 
33
    struct addrinfo hints;
 
34
 
 
35
    memset(&hints, 0, sizeof(hints));
 
36
    hints.ai_socktype=SOCK_STREAM;
 
37
    hints.ai_protocol=PF_UNSPEC;
 
38
    hints.ai_family=AF_UNSPEC;
 
39
    return getaddrinfo(name, NULL, &hints, result);
 
40
}
 
41
 
 
42
/* XXX FIXME: doesn't detect if an IPv6-mapped IPv4 address
 
43
 * matches a real IPv4 address */
 
44
static int compareaddr(const struct addrinfo *a1, const struct addrinfo *a2)
 
45
{
 
46
    if (a1->ai_family != a2->ai_family) return FALSE;
 
47
    if (a1->ai_addrlen != a2->ai_addrlen) return FALSE;
 
48
    return (!memcmp(a1->ai_addr, a2->ai_addr, a1->ai_addrlen));
 
49
}
 
50
 
29
51
static int is_ip_alias(const char *name1,const char *name2)
30
52
/*
31
53
 * Given two hostnames as arguments, returns TRUE if they
34
56
 * the calling function does them.
35
57
 */
36
58
{
37
 
    typedef unsigned char address_t[sizeof (struct in_addr)]; 
38
 
    typedef struct _address_e
39
 
    {
40
 
        struct _address_e *next;
41
 
        address_t address;
42
 
    } 
43
 
    address_e;
44
 
    address_e *host_a_addr=0, *host_b_addr=0;   /* assignments pacify -Wall */
45
 
    address_e *dummy_addr;
46
 
 
47
 
    int i;
48
 
    struct hostent *hp;
49
 
    char **p;
50
 
 
51
 
    hp = gethostbyname((char*)name1);
52
 
 
53
 
    dummy_addr = (address_e *)NULL;
54
 
 
55
 
    for (i=0,p = hp->h_addr_list; *p != 0; i++,p++)
56
 
    {
57
 
        struct in_addr in;
58
 
        (void) memcpy(&in.s_addr, *p, sizeof (in.s_addr));
59
 
        xalloca(host_a_addr, address_e *, sizeof (address_e));
60
 
        memset (host_a_addr,0, sizeof (address_e));
61
 
        host_a_addr->next = dummy_addr;
62
 
        (void) memcpy(&host_a_addr->address, *p, sizeof (in.s_addr));
63
 
        dummy_addr = host_a_addr;
64
 
    }
65
 
 
66
 
    hp = gethostbyname((char*)name2);
67
 
 
68
 
    dummy_addr = (address_e *)NULL;
69
 
    for (i=0,p = hp->h_addr_list; *p != 0; i++,p++)
70
 
    {
71
 
        struct in_addr in;
72
 
        (void) memcpy(&in.s_addr, *p, sizeof (in.s_addr));
73
 
        xalloca(host_b_addr, address_e *, sizeof (address_e));
74
 
        memset (host_b_addr,0, sizeof (address_e));
75
 
        host_b_addr->next = dummy_addr;
76
 
        (void) memcpy(&host_b_addr->address, *p, sizeof (in.s_addr));
77
 
        dummy_addr = host_b_addr;
78
 
    }
79
 
 
80
 
    while (host_a_addr)
81
 
    {
82
 
        while (host_b_addr)
83
 
        {
84
 
            if (!memcmp(host_b_addr->address,host_a_addr->address, sizeof (address_t)))
85
 
                return (TRUE);
86
 
 
87
 
            host_b_addr = host_b_addr->next;
 
59
    int rc = FALSE;
 
60
 
 
61
    struct addrinfo *res1 = NULL, *res2 = NULL, *ii, *ij;
 
62
 
 
63
    if (getaddresses(&res1, name1))
 
64
        goto found;
 
65
 
 
66
    if (getaddresses(&res2, name2))
 
67
        goto found;
 
68
 
 
69
    for (ii = res1 ; ii ; ii = ii -> ai_next) {
 
70
        for (ij = res2 ; ij ; ij = ij -> ai_next) {
 
71
            if (compareaddr(ii, ij)) {
 
72
                rc = TRUE;
 
73
                goto found;
 
74
            }
88
75
        }
89
 
        host_a_addr = host_a_addr->next;
90
76
    }
91
 
    return (FALSE);
 
77
 
 
78
found:
 
79
    if (res2)
 
80
        freeaddrinfo(res2);
 
81
    if (res1)
 
82
        freeaddrinfo(res1);
 
83
    return rc;
92
84
}
93
85
 
94
86
int is_host_alias(const char *name, struct query *ctl)
95
87
/* determine whether name is a DNS alias of the mailserver for this query */
96
88
{
97
 
    struct hostent      *he,*he_st;
98
89
    struct mxentry      *mxp, *mxrecords;
99
90
    struct idlist       *idl;
100
 
    int                 namelen;
 
91
    int                 namelen, e;
 
92
    struct addrinfo     hints, *res, *res_st;
101
93
 
102
 
    struct hostdata *lead_server = 
 
94
    struct hostdata *lead_server =
103
95
        ctl->server.lead_server ? ctl->server.lead_server : &ctl->server;
104
96
 
105
97
    /*
107
99
     * many cases.
108
100
     *
109
101
     * (1) check against the `true name' deduced from the poll label
110
 
     * and the via option (if present) at the beginning of the poll cycle.  
 
102
     * and the via option (if present) at the beginning of the poll cycle.
111
103
     * Odds are good this will either be the mailserver's FQDN or a suffix of
112
104
     * it with the mailserver's domain's default host name omitted.
113
105
     *
161
153
     * delivering the current message or anything else from the
162
154
     * current server until it's back up.
163
155
     */
164
 
    if ((he = gethostbyname((char*)name)) != (struct hostent *)NULL)
 
156
    memset(&hints, 0, sizeof hints);
 
157
    hints.ai_family=AF_UNSPEC;
 
158
    hints.ai_protocol=PF_UNSPEC;
 
159
    hints.ai_socktype=SOCK_STREAM;
 
160
    hints.ai_flags=AI_CANONNAME;
 
161
 
 
162
    e = getaddrinfo(name, NULL, &hints, &res);
 
163
    if (e == 0)
165
164
    {
166
 
        if (strcasecmp(ctl->server.truename, he->h_name) == 0)
 
165
        int rr = (strcasecmp(ctl->server.truename, res->ai_canonname) == 0);
 
166
        freeaddrinfo(res);
 
167
        if (rr)
167
168
            goto match;
168
 
        else if (((he_st = gethostbyname(ctl->server.truename)) != (struct hostent *)NULL) && ctl->server.checkalias)
 
169
        else if (ctl->server.checkalias && 0 == getaddrinfo(ctl->server.truename, NULL, &hints, &res_st))
169
170
        {
 
171
            freeaddrinfo(res_st);
170
172
            if (outlevel >= O_DEBUG)
171
173
                report(stdout, GT_("Checking if %s is really the same node as %s\n"),ctl->server.truename,name);
172
174
            if (is_ip_alias(ctl->server.truename,name) == TRUE)
178
180
            if (outlevel >= O_DEBUG)
179
181
                report(stdout, GT_("No, their IP addresses don't match\n"));
180
182
            return(FALSE);
 
183
        } else {
 
184
            return(FALSE);
181
185
        }
182
 
        else
183
 
            return(FALSE);
184
186
    }
185
187
    else
186
 
        switch (h_errno)
 
188
        switch (e)
187
189
        {
188
 
        case HOST_NOT_FOUND:    /* specified host is unknown */
189
 
#ifndef __BEOS__
190
 
        case NO_ADDRESS:        /* valid, but does not have an IP address */
191
 
            break;
192
 
#endif
193
 
        case NO_RECOVERY:       /* non-recoverable name server error */
194
 
        case TRY_AGAIN:         /* temporary error on authoritative server */
195
 
        default:
196
 
            if (outlevel != O_SILENT)
197
 
                report_complete(stdout, "\n");  /* terminate the progress message */
198
 
            report(stderr,
199
 
                GT_("nameserver failure while looking for `%s' during poll of %s.\n"),
200
 
                name, ctl->server.pollname);
201
 
            ctl->errcount++;
202
 
            break;
 
190
            case EAI_NONAME:    /* specified host is unknown */
 
191
                break;
 
192
 
 
193
            default:
 
194
                if (outlevel != O_SILENT)
 
195
                    report_complete(stdout, "\n");      /* terminate the progress message */
 
196
                report(stderr,
 
197
                        GT_("nameserver failure while looking for '%s' during poll of %s: %s\n"),
 
198
                        name, ctl->server.pollname, gai_strerror(e));
 
199
                ctl->errcount++;
 
200
                break;
203
201
        }
204
202
 
205
203
    /*
213
211
        switch (h_errno)
214
212
        {
215
213
        case HOST_NOT_FOUND:    /* specified host is unknown */
216
 
#ifndef __BEOS__
 
214
#ifdef NO_ADDRESS
217
215
        case NO_ADDRESS:        /* valid, but does not have an IP address */
218
216
            return(FALSE);
219
 
            break;
220
217
#endif
221
218
        case NO_RECOVERY:       /* non-recoverable name server error */
222
219
        case TRY_AGAIN:         /* temporary error on authoritative server */
227
224
            ctl->errcount++;
228
225
            break;
229
226
        }
230
 
    }
231
 
    else
232
 
    {
 
227
    } else {
233
228
        for (mxp = mxrecords; mxp->name; mxp++)
234
 
            if (strcasecmp(ctl->server.truename, mxp->name) == 0)
 
229
            if (strcasecmp(ctl->server.truename, mxp->name) == 0
 
230
                    || is_ip_alias(ctl->server.truename, mxp->name) == TRUE)
235
231
                goto match;
236
232
        return(FALSE);
237
233
    match:;
242
238
    return(TRUE);
243
239
#endif /* HAVE_RES_SEARCH */
244
240
}
245
 
#endif /* HAVE_GETHOSTBYNAME */
246
241
 
247
242
/* checkalias.c ends here */